Home | History | Annotate | Download | only in PlatformDriOverrideDxe
      1 /** @file
      2   Implementation of the shared functions to do the platform driver vverride mapping.
      3 
      4   Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "InternalPlatDriOverrideDxe.h"
     16 
     17 #define PLATFORM_OVERRIDE_ITEM_SIGNATURE      SIGNATURE_32('p','d','o','i')
     18  typedef struct _PLATFORM_OVERRIDE_ITEM {
     19   UINTN                                 Signature;
     20   LIST_ENTRY                            Link;
     21   UINT32                                DriverInfoNum;
     22   EFI_DEVICE_PATH_PROTOCOL              *ControllerDevicePath;
     23   ///
     24   /// List of DRIVER_IMAGE_INFO
     25   ///
     26   LIST_ENTRY                            DriverInfoList;
     27   EFI_HANDLE                            LastReturnedImageHandle;
     28 } PLATFORM_OVERRIDE_ITEM;
     29 
     30 #define DRIVER_IMAGE_INFO_SIGNATURE           SIGNATURE_32('p','d','i','i')
     31 typedef struct _DRIVER_IMAGE_INFO {
     32   UINTN                                 Signature;
     33   LIST_ENTRY                            Link;
     34   EFI_HANDLE                            ImageHandle;
     35   EFI_DEVICE_PATH_PROTOCOL              *DriverImagePath;
     36   BOOLEAN                               UnLoadable;
     37   BOOLEAN                               UnStartable;
     38 } DRIVER_IMAGE_INFO;
     39 
     40 #define DEVICE_PATH_STACK_ITEM_SIGNATURE      SIGNATURE_32('d','p','s','i')
     41 typedef struct _DEVICE_PATH_STACK_ITEM{
     42   UINTN                                 Signature;
     43   LIST_ENTRY                            Link;
     44   EFI_DEVICE_PATH_PROTOCOL              *DevicePath;
     45 } DEVICE_PATH_STACK_ITEM;
     46 
     47 
     48 LIST_ENTRY   mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack);
     49 
     50 /**
     51   Push a controller device path into a globle device path list.
     52 
     53   @param  DevicePath     The controller device path to push into stack
     54 
     55   @retval EFI_SUCCESS    Device path successfully pushed into the stack.
     56 
     57 **/
     58 EFI_STATUS
     59 EFIAPI
     60 PushDevPathStack (
     61   IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath
     62   )
     63 {
     64   DEVICE_PATH_STACK_ITEM  *DevicePathStackItem;
     65 
     66   DevicePathStackItem = AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM));
     67   ASSERT (DevicePathStackItem != NULL);
     68   DevicePathStackItem->Signature = DEVICE_PATH_STACK_ITEM_SIGNATURE;
     69   DevicePathStackItem->DevicePath = DuplicateDevicePath (DevicePath);
     70   InsertTailList (&mDevicePathStack, &DevicePathStackItem->Link);
     71   return EFI_SUCCESS;
     72 }
     73 
     74 
     75 /**
     76   Pop a controller device path from a globle device path list
     77 
     78   @param  DevicePath     The controller device path popped from stack
     79 
     80   @retval EFI_SUCCESS    Controller device path successfully popped.
     81   @retval EFI_NOT_FOUND  Stack is empty.
     82 
     83 **/
     84 EFI_STATUS
     85 EFIAPI
     86 PopDevPathStack (
     87   OUT  EFI_DEVICE_PATH_PROTOCOL    **DevicePath
     88   )
     89 {
     90   DEVICE_PATH_STACK_ITEM  *DevicePathStackItem;
     91   LIST_ENTRY              *ItemListIndex;
     92 
     93   ItemListIndex = mDevicePathStack.BackLink;
     94   //
     95   // Check if the stack is empty
     96   //
     97   if (ItemListIndex != &mDevicePathStack){
     98     DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);
     99     if (DevicePath != NULL) {
    100       *DevicePath = DuplicateDevicePath (DevicePathStackItem->DevicePath);
    101     }
    102     FreePool (DevicePathStackItem->DevicePath);
    103     RemoveEntryList (&DevicePathStackItem->Link);
    104     FreePool (DevicePathStackItem);
    105     return EFI_SUCCESS;
    106   }
    107   return EFI_NOT_FOUND;
    108 }
    109 
    110 
    111 /**
    112   Check whether a controller device path is in a globle device path list
    113 
    114   @param  DevicePath     The controller device path to check
    115 
    116   @retval TRUE           DevicePath exists in the stack.
    117   @retval FALSE          DevicePath does not exist in the stack.
    118 
    119 **/
    120 BOOLEAN
    121 EFIAPI
    122 CheckExistInStack (
    123   IN  EFI_DEVICE_PATH_PROTOCOL    *DevicePath
    124   )
    125 {
    126   DEVICE_PATH_STACK_ITEM  *DevicePathStackItem;
    127   LIST_ENTRY              *ItemListIndex;
    128   UINTN                   DevicePathSize;
    129 
    130   ItemListIndex = mDevicePathStack.BackLink;
    131   while (ItemListIndex != &mDevicePathStack){
    132     DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);
    133     DevicePathSize = GetDevicePathSize (DevicePath);
    134     if (DevicePathSize == GetDevicePathSize (DevicePathStackItem->DevicePath)) {
    135       if (CompareMem (DevicePath, DevicePathStackItem->DevicePath, DevicePathSize) == 0) {
    136         return TRUE;
    137       }
    138     }
    139     ItemListIndex = ItemListIndex->BackLink;
    140   }
    141 
    142   return FALSE;
    143 }
    144 
    145 /**
    146   Update the FV file device path if it is not valid.
    147 
    148   According to a file GUID, check a Fv file device path is valid. If it is invalid,
    149   try to return the valid device path.
    150   FV address maybe changes for memory layout adjust from time to time, use this function
    151   could promise the Fv file device path is right.
    152 
    153   @param  DevicePath               On input, the FV file device path to check
    154                                    On output, the updated valid FV file device path
    155   @param  FileGuid                 The FV file GUID
    156   @param  CallerImageHandle        Image handle of the caller
    157 
    158   @retval EFI_INVALID_PARAMETER    the input DevicePath or FileGuid is invalid
    159                                    parameter
    160   @retval EFI_UNSUPPORTED          the input DevicePath does not contain FV file
    161                                    GUID at all
    162   @retval EFI_ALREADY_STARTED      the input DevicePath has pointed to FV file, it
    163                                    is valid
    164   @retval EFI_SUCCESS              Successfully updated the invalid DevicePath,
    165                                    and return the updated device path in DevicePath
    166 
    167 **/
    168 EFI_STATUS
    169 EFIAPI
    170 UpdateFvFileDevicePath (
    171   IN  OUT EFI_DEVICE_PATH_PROTOCOL      **DevicePath,
    172   IN  EFI_GUID                          *FileGuid,
    173   IN  EFI_HANDLE                        CallerImageHandle
    174   )
    175 {
    176   EFI_DEVICE_PATH_PROTOCOL      *TempDevicePath;
    177   EFI_DEVICE_PATH_PROTOCOL      *LastDeviceNode;
    178   EFI_STATUS                    Status;
    179   EFI_GUID                      *GuidPoint;
    180   UINTN                         Index;
    181   UINTN                         FvHandleCount;
    182   EFI_HANDLE                    *FvHandleBuffer;
    183   EFI_FV_FILETYPE               Type;
    184   UINTN                         Size;
    185   EFI_FV_FILE_ATTRIBUTES        Attributes;
    186   UINT32                        AuthenticationStatus;
    187   BOOLEAN                       FindFvFile;
    188   EFI_LOADED_IMAGE_PROTOCOL     *LoadedImage;
    189   EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
    190   MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;
    191   EFI_HANDLE                    FoundFvHandle;
    192   EFI_DEVICE_PATH_PROTOCOL      *NewDevicePath;
    193   BOOLEAN                       HasFvNode;
    194 
    195   if (DevicePath == NULL) {
    196     return EFI_INVALID_PARAMETER;
    197   }
    198 
    199   if (*DevicePath == NULL) {
    200     return EFI_INVALID_PARAMETER;
    201   }
    202 
    203   //
    204   // Check whether the device path points to the default the input FV file
    205   //
    206   TempDevicePath = *DevicePath;
    207   LastDeviceNode = TempDevicePath;
    208   while (!IsDevicePathEnd (TempDevicePath)) {
    209      LastDeviceNode = TempDevicePath;
    210      TempDevicePath = NextDevicePathNode (TempDevicePath);
    211   }
    212   GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode);
    213   if (GuidPoint == NULL) {
    214     //
    215     // If this option does not point to a FV file, just return EFI_UNSUPPORTED.
    216     //
    217     return EFI_UNSUPPORTED;
    218   }
    219 
    220   if (FileGuid != NULL) {
    221     if (!CompareGuid (GuidPoint, FileGuid)) {
    222       //
    223       // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED
    224       //
    225       return EFI_UNSUPPORTED;
    226     }
    227   } else {
    228     FileGuid = GuidPoint;
    229   }
    230 
    231   //
    232   // Check to see if the device path contains memory map node
    233   //
    234   TempDevicePath = *DevicePath;
    235   HasFvNode = FALSE;
    236   while (!IsDevicePathEnd (TempDevicePath)) {
    237     //
    238     // Use old Device Path
    239     //
    240     if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH &&
    241         DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) {
    242       HasFvNode = TRUE;
    243       break;
    244     }
    245     TempDevicePath = NextDevicePathNode (TempDevicePath);
    246   }
    247 
    248   if (!HasFvNode) {
    249     return EFI_UNSUPPORTED;
    250   }
    251 
    252   //
    253   // Check whether the input Fv file device path is valid
    254   //
    255   TempDevicePath = *DevicePath;
    256   FoundFvHandle = NULL;
    257   Status = gBS->LocateDevicePath (
    258                   &gEfiFirmwareVolume2ProtocolGuid,
    259                   &TempDevicePath,
    260                   &FoundFvHandle
    261                   );
    262   if (!EFI_ERROR (Status)) {
    263     Status = gBS->HandleProtocol (
    264                     FoundFvHandle,
    265                     &gEfiFirmwareVolume2ProtocolGuid,
    266                     (VOID **) &Fv
    267                     );
    268     if (!EFI_ERROR (Status)) {
    269       //
    270       // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there
    271       //
    272       Status = Fv->ReadFile (
    273                      Fv,
    274                      FileGuid,
    275                      NULL,
    276                      &Size,
    277                      &Type,
    278                      &Attributes,
    279                      &AuthenticationStatus
    280                      );
    281       if (!EFI_ERROR (Status)) {
    282         return EFI_ALREADY_STARTED;
    283       }
    284     }
    285   }
    286 
    287   //
    288   // Look for the input wanted FV file in current FV
    289   // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV
    290   //
    291   FindFvFile = FALSE;
    292   FoundFvHandle = NULL;
    293   Status = gBS->HandleProtocol (
    294                   CallerImageHandle,
    295                   &gEfiLoadedImageProtocolGuid,
    296                   (VOID **) &LoadedImage
    297                   );
    298   if (!EFI_ERROR (Status)) {
    299     Status = gBS->HandleProtocol (
    300                     LoadedImage->DeviceHandle,
    301                     &gEfiFirmwareVolume2ProtocolGuid,
    302                     (VOID **) &Fv
    303                     );
    304     if (!EFI_ERROR (Status)) {
    305       Status = Fv->ReadFile (
    306                      Fv,
    307                      FileGuid,
    308                      NULL,
    309                      &Size,
    310                      &Type,
    311                      &Attributes,
    312                      &AuthenticationStatus
    313                      );
    314       if (!EFI_ERROR (Status)) {
    315         FindFvFile = TRUE;
    316         FoundFvHandle = LoadedImage->DeviceHandle;
    317       }
    318     }
    319   }
    320   //
    321   // Second, if fail to find, try to enumerate all FV
    322   //
    323   if (!FindFvFile) {
    324     gBS->LocateHandleBuffer (
    325            ByProtocol,
    326            &gEfiFirmwareVolume2ProtocolGuid,
    327            NULL,
    328            &FvHandleCount,
    329            &FvHandleBuffer
    330            );
    331     for (Index = 0; Index < FvHandleCount; Index++) {
    332       gBS->HandleProtocol (
    333              FvHandleBuffer[Index],
    334              &gEfiFirmwareVolume2ProtocolGuid,
    335              (VOID **) &Fv
    336              );
    337 
    338       Status = Fv->ReadFile (
    339                      Fv,
    340                      FileGuid,
    341                      NULL,
    342                      &Size,
    343                      &Type,
    344                      &Attributes,
    345                      &AuthenticationStatus
    346                      );
    347       if (EFI_ERROR (Status)) {
    348         //
    349         // Skip if input Fv file not in the FV
    350         //
    351         continue;
    352       }
    353       FindFvFile = TRUE;
    354       FoundFvHandle = FvHandleBuffer[Index];
    355       break;
    356     }
    357   }
    358 
    359   if (FindFvFile) {
    360     //
    361     // Build the shell device path
    362     //
    363     NewDevicePath = DevicePathFromHandle (FoundFvHandle);
    364     EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);
    365     NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);
    366     *DevicePath = NewDevicePath;
    367     return EFI_SUCCESS;
    368   }
    369   return EFI_NOT_FOUND;
    370 }
    371 
    372 /**
    373   Gets the data and size of a variable.
    374 
    375   Read the EFI variable (VendorGuid/Name) and return a dynamically allocated
    376   buffer, and the size of the buffer. If failure return NULL.
    377 
    378   @param  Name                     String part of EFI variable name
    379   @param  VendorGuid               GUID part of EFI variable name
    380   @param  VariableSize             Returns the size of the EFI variable that was
    381                                    read
    382 
    383   @return Dynamically allocated memory that contains a copy of the EFI variable.
    384           Caller is responsible freeing the buffer.
    385   @retval NULL                     Variable was not read
    386 
    387 **/
    388 VOID *
    389 EFIAPI
    390 GetVariableAndSize (
    391   IN  CHAR16              *Name,
    392   IN  EFI_GUID            *VendorGuid,
    393   OUT UINTN               *VariableSize
    394   )
    395 {
    396   EFI_STATUS  Status;
    397   UINTN       BufferSize;
    398   VOID        *Buffer;
    399 
    400   Buffer = NULL;
    401 
    402   //
    403   // Pass in a zero size buffer to find the required buffer size.
    404   //
    405   BufferSize  = 0;
    406   Status      = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
    407   if (Status == EFI_BUFFER_TOO_SMALL) {
    408     //
    409     // Allocate the buffer to return
    410     //
    411     Buffer = AllocateZeroPool (BufferSize);
    412     if (Buffer == NULL) {
    413       return NULL;
    414     }
    415     //
    416     // Read variable into the allocated buffer.
    417     //
    418     Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);
    419     if (EFI_ERROR (Status)) {
    420       BufferSize = 0;
    421     }
    422   }
    423 
    424   *VariableSize = BufferSize;
    425   return Buffer;
    426 }
    427 
    428 /**
    429   Connect to the handle to a device on the device path.
    430 
    431   This function will create all handles associate with every device
    432   path node. If the handle associate with one device path node can not
    433   be created success, then still give one chance to do the dispatch,
    434   which load the missing drivers if possible.
    435 
    436   @param  DevicePathToConnect      The device path which will be connected, it can
    437                                    be a multi-instance device path
    438 
    439   @retval EFI_SUCCESS              All handles associate with every device path
    440                                    node have been created
    441   @retval EFI_OUT_OF_RESOURCES     There is no resource to create new handles
    442   @retval EFI_NOT_FOUND            Create the handle associate with one device
    443                                    path node failed
    444 
    445 **/
    446 EFI_STATUS
    447 EFIAPI
    448 ConnectDevicePath (
    449   IN EFI_DEVICE_PATH_PROTOCOL  *DevicePathToConnect
    450   )
    451 {
    452   EFI_STATUS                Status;
    453   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    454   EFI_DEVICE_PATH_PROTOCOL  *CopyOfDevicePath;
    455   EFI_DEVICE_PATH_PROTOCOL  *Instance;
    456   EFI_DEVICE_PATH_PROTOCOL  *RemainingDevicePath;
    457   EFI_DEVICE_PATH_PROTOCOL  *Next;
    458   EFI_HANDLE                Handle;
    459   EFI_HANDLE                PreviousHandle;
    460   UINTN                     Size;
    461 
    462   if (DevicePathToConnect == NULL) {
    463     return EFI_SUCCESS;
    464   }
    465 
    466   DevicePath        = DuplicateDevicePath (DevicePathToConnect);
    467   CopyOfDevicePath  = DevicePath;
    468   if (DevicePath == NULL) {
    469     return EFI_OUT_OF_RESOURCES;
    470   }
    471 
    472   do {
    473     //
    474     // The outer loop handles multi instance device paths.
    475     // Only console variables contain multiple instance device paths.
    476     //
    477     // After this call DevicePath points to the next Instance
    478     //
    479     Instance  = GetNextDevicePathInstance (&DevicePath, &Size);
    480     ASSERT (Instance != NULL);
    481 
    482     Next      = Instance;
    483     while (!IsDevicePathEndType (Next)) {
    484       Next = NextDevicePathNode (Next);
    485     }
    486 
    487     SetDevicePathEndNode (Next);
    488 
    489     //
    490     // Start the real work of connect with RemainingDevicePath
    491     //
    492     PreviousHandle = NULL;
    493     do {
    494       //
    495       // Find the handle that best matches the Device Path. If it is only a
    496       // partial match the remaining part of the device path is returned in
    497       // RemainingDevicePath.
    498       //
    499       RemainingDevicePath = Instance;
    500       Status              = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
    501 
    502       if (!EFI_ERROR (Status)) {
    503         if (Handle == PreviousHandle) {
    504           //
    505           // If no forward progress is made try invoking the Dispatcher.
    506           // A new FV may have been added to the system an new drivers
    507           // may now be found.
    508           // Status == EFI_SUCCESS means a driver was dispatched
    509           // Status == EFI_NOT_FOUND means no new drivers were dispatched
    510           //
    511           Status = gDS->Dispatch ();
    512         }
    513 
    514         if (!EFI_ERROR (Status)) {
    515           PreviousHandle = Handle;
    516           //
    517           // Connect all drivers that apply to Handle and RemainingDevicePath,
    518           // the Recursive flag is FALSE so only one level will be expanded.
    519           //
    520           // Do not check the connect status here, if the connect controller fail,
    521           // then still give the chance to do dispatch, because partial
    522           // RemainingDevicepath may be in the new FV
    523           //
    524           // 1. If the connect fails, RemainingDevicepath and handle will not
    525           //    change, so next time will do the dispatch, then dispatch's status
    526           //    will take effect
    527           // 2. If the connect succeeds, the RemainingDevicepath and handle will
    528           //    change, then avoid the dispatch, we have chance to continue the
    529           //    next connection
    530           //
    531           gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
    532         }
    533       }
    534       //
    535       // Loop until RemainingDevicePath is an empty device path
    536       //
    537     } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));
    538 
    539   } while (DevicePath != NULL);
    540 
    541   if (CopyOfDevicePath != NULL) {
    542     FreePool (CopyOfDevicePath);
    543   }
    544   //
    545   // All handle with DevicePath exists in the handle database
    546   //
    547   return Status;
    548 }
    549 
    550 /**
    551   Free all the mapping database memory resource and initialize the mapping list entry.
    552 
    553   @param  MappingDataBase          Mapping database list entry pointer
    554 
    555   @retval EFI_SUCCESS              Mapping database successfully freed
    556   @retval EFI_INVALID_PARAMETER    MappingDataBase is NULL
    557 
    558 **/
    559 EFI_STATUS
    560 EFIAPI
    561 FreeMappingDatabase (
    562   IN  OUT  LIST_ENTRY            *MappingDataBase
    563   )
    564 {
    565   LIST_ENTRY                  *OverrideItemListIndex;
    566   LIST_ENTRY                  *ImageInfoListIndex;
    567   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
    568   DRIVER_IMAGE_INFO           *DriverImageInfo;
    569 
    570   if (MappingDataBase == NULL) {
    571     return EFI_INVALID_PARAMETER;
    572   }
    573 
    574   OverrideItemListIndex = GetFirstNode (MappingDataBase);
    575   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
    576     OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
    577     //
    578     // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[]
    579     //
    580     if (OverrideItem->ControllerDevicePath != NULL){
    581       FreePool (OverrideItem->ControllerDevicePath);
    582     }
    583 
    584     ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
    585     while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
    586       //
    587       // Free DRIVER_IMAGE_INFO.DriverImagePath[]
    588       //
    589       DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
    590       if (DriverImageInfo->DriverImagePath != NULL) {
    591         FreePool(DriverImageInfo->DriverImagePath);
    592       }
    593       //
    594       // Free DRIVER_IMAGE_INFO itself
    595       //
    596       ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
    597       RemoveEntryList (&DriverImageInfo->Link);
    598       FreePool (DriverImageInfo);
    599     }
    600     //
    601     // Free PLATFORM_OVERRIDE_ITEM itself
    602     //
    603     OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
    604     RemoveEntryList (&OverrideItem->Link);
    605     FreePool (OverrideItem);
    606   }
    607 
    608   InitializeListHead (MappingDataBase);
    609   return EFI_SUCCESS;
    610 }
    611 
    612 
    613 /**
    614   Create the mapping database according to variable.
    615 
    616   Read the environment variable(s) that contain the override mappings from Controller Device Path to
    617   a set of Driver Device Paths, and create the mapping database in memory with those variable info.
    618   VariableLayout{
    619   //
    620   // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load.
    621   // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store
    622   // large mapping infos.
    623   // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, ....
    624   //
    625   UINT32                         NotEnd;               //Zero is the last one.
    626   //
    627   // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths
    628   // There are often multi mapping entries in a variable.
    629   //
    630   UINT32                         SIGNATURE;            //SIGNATURE_32('p','d','o','i')
    631   UINT32                         DriverNum;
    632   EFI_DEVICE_PATH_PROTOCOL       ControllerDevicePath[];
    633   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    634   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    635   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    636   ......
    637   UINT32                         NotEnd;                //Zero is the last one.
    638   UINT32                         SIGNATURE;
    639   UINT32                         DriverNum;
    640   EFI_DEVICE_PATH_PROTOCOL       ControllerDevicePath[];
    641   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    642   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    643   EFI_DEVICE_PATH_PROTOCOL       DriverDevicePath[];
    644   ......
    645   }
    646 
    647   @param  MappingDataBase          Mapping database list entry pointer
    648 
    649   @retval EFI_SUCCESS              Create the mapping database in memory successfully
    650   @retval EFI_INVALID_PARAMETER    MappingDataBase pointer is null
    651   @retval EFI_NOT_FOUND            Cannot find the 'PlatDriOver' NV variable
    652   @retval EFI_VOLUME_CORRUPTED     The found NV variable is corrupted
    653 
    654 **/
    655 EFI_STATUS
    656 EFIAPI
    657 InitOverridesMapping (
    658   OUT  LIST_ENTRY            *MappingDataBase
    659   )
    660 {
    661   UINTN                       BufferSize;
    662   VOID                        *VariableBuffer;
    663   UINT8                       *VariableIndex;
    664   UINTN                       VariableNum;
    665   CHAR16                      OverrideVariableName[40];
    666   UINT32                      NotEnd;
    667   UINT32                      DriverNumber;
    668   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
    669   DRIVER_IMAGE_INFO           *DriverImageInfo;
    670   BOOLEAN                     Corrupted;
    671   UINT32                      Signature;
    672   EFI_DEVICE_PATH_PROTOCOL    *ControllerDevicePath;
    673   EFI_DEVICE_PATH_PROTOCOL    *DriverDevicePath;
    674   UINTN                       Index;
    675 
    676   if (MappingDataBase == NULL) {
    677     return EFI_INVALID_PARAMETER;
    678   }
    679 
    680   //
    681   // Check the environment variable(s) that contain the override mappings .
    682   //
    683   VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);
    684   ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
    685   if (VariableBuffer == NULL) {
    686     return EFI_NOT_FOUND;
    687   }
    688 
    689   //
    690   // Traverse all variables.
    691   //
    692   VariableNum = 1;
    693   Corrupted = FALSE;
    694   NotEnd = 0;
    695   do {
    696     VariableIndex = VariableBuffer;
    697     if (VariableIndex + sizeof (UINT32) > (UINT8 *) VariableBuffer + BufferSize) {
    698       Corrupted = TRUE;
    699     } else {
    700       //
    701       // End flag
    702       //
    703       NotEnd = *(UINT32*) VariableIndex;
    704     }
    705     //
    706     // Traverse the entries containing the mapping that Controller Device Path
    707     // to a set of Driver Device Paths within this variable.
    708     //
    709     VariableIndex = VariableIndex + sizeof (UINT32);
    710     while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) {
    711       //
    712       // Check signature of this entry
    713       //
    714       if (VariableIndex + sizeof (UINT32) > (UINT8 *) VariableBuffer + BufferSize) {
    715         Corrupted = TRUE;
    716         break;
    717       }
    718       Signature = *(UINT32 *) VariableIndex;
    719       if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) {
    720         Corrupted = TRUE;
    721         break;
    722       }
    723       //
    724       // Create PLATFORM_OVERRIDE_ITEM for this mapping
    725       //
    726       OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
    727       ASSERT (OverrideItem != NULL);
    728       OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
    729       InitializeListHead (&OverrideItem->DriverInfoList);
    730       VariableIndex = VariableIndex + sizeof (UINT32);
    731       //
    732       // Get DriverNum
    733       //
    734       if (VariableIndex + sizeof (UINT32) >= (UINT8 *) VariableBuffer + BufferSize) {
    735         Corrupted = TRUE;
    736         break;
    737       }
    738       DriverNumber = *(UINT32*) VariableIndex;
    739       OverrideItem->DriverInfoNum = DriverNumber;
    740       VariableIndex = VariableIndex + sizeof (UINT32);
    741       //
    742       // Get ControllerDevicePath[]
    743       //
    744       ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
    745       OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
    746       VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath);
    747       //
    748       // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
    749       //
    750       VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
    751       //
    752       // Check buffer overflow.
    753       //
    754       if ((OverrideItem->ControllerDevicePath == NULL) || (VariableIndex < (UINT8 *) ControllerDevicePath) ||
    755           (VariableIndex > (UINT8 *) VariableBuffer + BufferSize)) {
    756         Corrupted = TRUE;
    757         break;
    758       }
    759 
    760       //
    761       // Get all DriverImageDevicePath[]
    762       //
    763       for (Index = 0; Index < DriverNumber; Index++) {
    764         //
    765         // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
    766         //
    767         DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
    768         ASSERT (DriverImageInfo != NULL);
    769         DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
    770 
    771         DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
    772         DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath);
    773         VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath);
    774         //
    775         // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
    776         //
    777         VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
    778 
    779         InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
    780 
    781         //
    782         // Check buffer overflow
    783         //
    784         if ((DriverImageInfo->DriverImagePath == NULL) || (VariableIndex < (UINT8 *) DriverDevicePath) ||
    785             (VariableIndex < (UINT8 *) VariableBuffer + BufferSize)) {
    786           Corrupted = TRUE;
    787           break;
    788         }
    789       }
    790       InsertTailList (MappingDataBase, &OverrideItem->Link);
    791       if (Corrupted) {
    792         break;
    793       }
    794     }
    795 
    796     FreePool (VariableBuffer);
    797     if (Corrupted) {
    798       FreeMappingDatabase (MappingDataBase);
    799       return EFI_VOLUME_CORRUPTED;
    800     }
    801 
    802     //
    803     // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
    804     // NotEnd indicates whether current variable is the end variable.
    805     //
    806     if (NotEnd != 0) {
    807       UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++);
    808       VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
    809       ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
    810       if (VariableBuffer == NULL) {
    811         FreeMappingDatabase (MappingDataBase);
    812         return EFI_VOLUME_CORRUPTED;
    813       }
    814     }
    815 
    816   } while (NotEnd != 0);
    817 
    818   return EFI_SUCCESS;
    819 }
    820 
    821 
    822 /**
    823   Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
    824 
    825   @param  OverrideItemListIndex    Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
    826 
    827   @return The needed size number
    828 
    829 **/
    830 UINTN
    831 EFIAPI
    832 GetOneItemNeededSize (
    833   IN  LIST_ENTRY            *OverrideItemListIndex
    834   )
    835 {
    836   UINTN                       NeededSize;
    837   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
    838   LIST_ENTRY                  *ImageInfoListIndex;
    839   DRIVER_IMAGE_INFO           *DriverImageInfo;
    840   UINTN                       DevicePathSize;
    841 
    842   NeededSize = 0;
    843   OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
    844   NeededSize += sizeof (UINT32); //UINT32  SIGNATURE;
    845   NeededSize += sizeof (UINT32); //UINT32  DriverNum;
    846   DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath);
    847   NeededSize += DevicePathSize; // ControllerDevicePath
    848   //
    849   // Align the controller device path
    850   //
    851   NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
    852   //
    853   // Traverse the Driver Info List of this Override Item
    854   //
    855   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
    856   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
    857     DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
    858     DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
    859     NeededSize += DevicePathSize; //DriverDevicePath
    860     //
    861     // Align the driver image device path
    862     //
    863     NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
    864     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
    865   }
    866 
    867   return NeededSize;
    868 }
    869 
    870 /**
    871   Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
    872   a set of Driver Device Paths.
    873 
    874   @retval EFI_SUCCESS  Delete all variable(s) successfully.
    875 
    876 **/
    877 EFI_STATUS
    878 EFIAPI
    879 DeleteOverridesVariables (
    880   VOID
    881   )
    882 {
    883   EFI_STATUS                  Status;
    884   VOID                        *VariableBuffer;
    885   UINTN                       VariableNum;
    886   UINTN                       BufferSize;
    887   UINTN                       Index;
    888   CHAR16                      OverrideVariableName[40];
    889 
    890   //
    891   // Get environment variable(s) number
    892   //
    893   VariableNum = 0;
    894   VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);
    895   VariableNum++;
    896   if (VariableBuffer == NULL) {
    897     return EFI_NOT_FOUND;
    898   }
    899   //
    900   // Check NotEnd to get all PlatDriOverX variable(s)
    901   //
    902   while ((VariableBuffer != NULL) && ((*(UINT32*)VariableBuffer) != 0)) {
    903     FreePool (VariableBuffer);
    904     UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);
    905     VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
    906     VariableNum++;
    907   }
    908 
    909   //
    910   // Delete PlatDriOver and all additional variables, if exist.
    911   //
    912   Status = gRT->SetVariable (
    913                   L"PlatDriOver",
    914                   &gEfiCallerIdGuid,
    915                   EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    916                   0,
    917                   NULL
    918                   );
    919   ASSERT (!EFI_ERROR (Status));
    920   for (Index = 1; Index < VariableNum; Index++) {
    921     UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index);
    922     Status = gRT->SetVariable (
    923                     OverrideVariableName,
    924                     &gEfiCallerIdGuid,
    925                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    926                     0,
    927                     NULL
    928                     );
    929     ASSERT (!EFI_ERROR (Status));
    930   }
    931   return EFI_SUCCESS;
    932 }
    933 
    934 
    935 /**
    936   Save the memory mapping database into NV environment variable(s).
    937 
    938   @param  MappingDataBase          Mapping database list entry pointer
    939 
    940   @retval EFI_SUCCESS              Save memory mapping database successfully
    941   @retval EFI_INVALID_PARAMETER    MappingDataBase pointer is null
    942 
    943 **/
    944 EFI_STATUS
    945 EFIAPI
    946 SaveOverridesMapping (
    947   IN  LIST_ENTRY              *MappingDataBase
    948   )
    949 {
    950   EFI_STATUS                  Status;
    951   VOID                        *VariableBuffer;
    952   UINT8                       *VariableIndex;
    953   UINTN                       NumIndex;
    954   CHAR16                      OverrideVariableName[40];
    955   UINT32                      NotEnd;
    956   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
    957   DRIVER_IMAGE_INFO           *DriverImageInfo;
    958   LIST_ENTRY                  *OverrideItemListIndex;
    959   LIST_ENTRY                  *ItemIndex;
    960   LIST_ENTRY                  *ImageInfoListIndex;
    961   UINTN                       VariableNeededSize;
    962   UINT64                      MaximumVariableStorageSize;
    963   UINT64                      RemainingVariableStorageSize;
    964   UINT64                      MaximumVariableSize;
    965   UINTN                       OneItemNeededSize;
    966 
    967   if (MappingDataBase == NULL) {
    968     return EFI_INVALID_PARAMETER;
    969   }
    970 
    971   if (IsListEmpty (MappingDataBase)) {
    972     Status = DeleteOverridesVariables ();
    973     return EFI_SUCCESS;
    974   }
    975 
    976   //
    977   // Get the the maximum size of an individual EFI variable in current system
    978   //
    979   gRT->QueryVariableInfo (
    980           EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
    981           &MaximumVariableStorageSize,
    982           &RemainingVariableStorageSize,
    983           &MaximumVariableSize
    984           );
    985 
    986   NumIndex = 0;
    987   OverrideItemListIndex = GetFirstNode (MappingDataBase);
    988   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
    989     //
    990     // Try to find the most proper variable size which <= MaximumVariableSize,
    991     // but can contain mapping info as much as possible
    992     //
    993     VariableNeededSize = sizeof (UINT32); // NotEnd;
    994     ItemIndex = OverrideItemListIndex;
    995     NotEnd = FALSE;
    996     //
    997     // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
    998     //
    999     while (!IsNull (MappingDataBase, ItemIndex)) {
   1000       OneItemNeededSize = GetOneItemNeededSize (ItemIndex);
   1001       //
   1002       // If the total size exceeds the MaximumVariableSize, then we must use
   1003       // multiple variables.
   1004       //
   1005       if ((VariableNeededSize +
   1006            OneItemNeededSize +
   1007            StrSize (L"PlatDriOver ")
   1008            ) >= MaximumVariableSize
   1009           ) {
   1010         NotEnd = TRUE;
   1011         break;
   1012       }
   1013 
   1014       VariableNeededSize += OneItemNeededSize;
   1015       ItemIndex = GetNextNode (MappingDataBase, ItemIndex);
   1016     }
   1017 
   1018     if (NotEnd != 0) {
   1019       if (VariableNeededSize == sizeof (UINT32)) {
   1020         //
   1021         // If an individual EFI variable cannot contain a single Item, return error
   1022         //
   1023         return EFI_OUT_OF_RESOURCES;
   1024       }
   1025     }
   1026 
   1027     //
   1028     // VariableNeededSize is the most proper variable size, allocate variable buffer
   1029     // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
   1030     //
   1031     VariableBuffer = AllocateZeroPool (VariableNeededSize);
   1032     ASSERT (VariableBuffer != NULL);
   1033     ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
   1034 
   1035     //
   1036     // Fill the variable buffer according to MappingDataBase
   1037     //
   1038     VariableIndex = VariableBuffer;
   1039     *(UINT32 *) VariableIndex = NotEnd;
   1040     VariableIndex += sizeof (UINT32); // pass NotEnd
   1041     //
   1042     // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
   1043     //
   1044     while (OverrideItemListIndex != ItemIndex){
   1045       *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
   1046       VariableIndex += sizeof (UINT32); // pass SIGNATURE
   1047 
   1048       OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
   1049       *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum;
   1050       VariableIndex += sizeof (UINT32); // pass DriverNum
   1051 
   1052       CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath));
   1053       VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath
   1054 
   1055       //
   1056       // Align the VariableIndex since the controller device path may not be aligned
   1057       //
   1058       VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
   1059       //
   1060       // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
   1061       //
   1062       ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1063       while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1064         DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
   1065         CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath));
   1066         VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath
   1067         //
   1068         // Align the VariableIndex since the driver image device path may not be aligned
   1069         //
   1070         VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
   1071         ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1072       }
   1073 
   1074       OverrideItemListIndex =  GetNextNode (MappingDataBase, OverrideItemListIndex);
   1075     }
   1076 
   1077     ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize);
   1078 
   1079     if (NumIndex == 0) {
   1080       UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver");
   1081     } else {
   1082       UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex );
   1083     }
   1084 
   1085     Status = gRT->SetVariable (
   1086                     OverrideVariableName,
   1087                     &gEfiCallerIdGuid,
   1088                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
   1089                     VariableNeededSize,
   1090                     VariableBuffer
   1091                     );
   1092     FreePool (VariableBuffer);
   1093 
   1094     if (EFI_ERROR (Status)) {
   1095       if (NumIndex > 0) {
   1096         //
   1097         // Delete all PlatDriOver variables when full mapping can't be set.
   1098         //
   1099         DeleteOverridesVariables ();
   1100       }
   1101       return Status;
   1102     }
   1103 
   1104     NumIndex ++;
   1105   }
   1106 
   1107   return EFI_SUCCESS;
   1108 }
   1109 
   1110 /**
   1111   Get the first Binding protocol which has the specific image handle.
   1112 
   1113   @param  ImageHandle          The Image handle
   1114   @param  BindingHandle        The BindingHandle of the found Driver Binding protocol.
   1115                                If Binding protocol is not found, it is set to NULL.
   1116 
   1117   @return                      Pointer into the Binding Protocol interface
   1118   @retval NULL                 The parameter is not valid or the binding protocol is not found.
   1119 
   1120 **/
   1121 EFI_DRIVER_BINDING_PROTOCOL *
   1122 EFIAPI
   1123 GetBindingProtocolFromImageHandle (
   1124   IN  EFI_HANDLE   ImageHandle,
   1125   OUT EFI_HANDLE   *BindingHandle
   1126   )
   1127 {
   1128   EFI_STATUS                        Status;
   1129   UINTN                             Index;
   1130   UINTN                             DriverBindingHandleCount;
   1131   EFI_HANDLE                        *DriverBindingHandleBuffer;
   1132   EFI_DRIVER_BINDING_PROTOCOL       *DriverBindingInterface;
   1133 
   1134   if (BindingHandle == NULL || ImageHandle == NULL) {
   1135     return NULL;
   1136   }
   1137   //
   1138   // Get all drivers which support driver binding protocol
   1139   //
   1140   DriverBindingHandleCount  = 0;
   1141   Status = gBS->LocateHandleBuffer (
   1142                   ByProtocol,
   1143                   &gEfiDriverBindingProtocolGuid,
   1144                   NULL,
   1145                   &DriverBindingHandleCount,
   1146                   &DriverBindingHandleBuffer
   1147                   );
   1148   if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
   1149     return NULL;
   1150   }
   1151 
   1152   for (Index = 0; Index < DriverBindingHandleCount; Index++) {
   1153     DriverBindingInterface = NULL;
   1154     Status = gBS->OpenProtocol (
   1155                     DriverBindingHandleBuffer[Index],
   1156                     &gEfiDriverBindingProtocolGuid,
   1157                     (VOID **) &DriverBindingInterface,
   1158                     NULL,
   1159                     NULL,
   1160                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1161                     );
   1162     if (EFI_ERROR (Status)) {
   1163       continue;
   1164     }
   1165 
   1166     if (DriverBindingInterface->ImageHandle == ImageHandle) {
   1167       *BindingHandle = DriverBindingHandleBuffer[Index];
   1168       FreePool (DriverBindingHandleBuffer);
   1169       return DriverBindingInterface;
   1170     }
   1171   }
   1172 
   1173   //
   1174   // If no Driver Binding Protocol instance is found
   1175   //
   1176   FreePool (DriverBindingHandleBuffer);
   1177   *BindingHandle = NULL;
   1178   return NULL;
   1179 }
   1180 
   1181 /**
   1182   Return the current TPL.
   1183 
   1184   @return Current TPL
   1185 
   1186 **/
   1187 EFI_TPL
   1188 GetCurrentTpl (
   1189   VOID
   1190   )
   1191 {
   1192   EFI_TPL                 Tpl;
   1193 
   1194   Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
   1195   gBS->RestoreTPL (Tpl);
   1196 
   1197   return Tpl;
   1198 }
   1199 
   1200 
   1201 /**
   1202   Retrieves the image handle of the platform override driver for a controller in
   1203   the system from the memory mapping database.
   1204 
   1205   @param  ControllerHandle         The device handle of the controller to check if
   1206                                    a driver override exists.
   1207   @param  DriverImageHandle        On input, the previously returnd driver image handle.
   1208                                    On output, a pointer to the next driver handle.
   1209                                    Passing in a pointer to NULL, will return the
   1210                                    first driver handle for ControllerHandle.
   1211   @param  MappingDataBase          Mapping database list entry pointer
   1212   @param  CallerImageHandle        The caller driver's image handle, for
   1213                                    UpdateFvFileDevicePath use.
   1214 
   1215   @retval EFI_INVALID_PARAMETER    The handle specified by ControllerHandle is not
   1216                                    a valid handle.  Or DriverImagePath is not a
   1217                                    device path that was returned on a previous call
   1218                                    to GetDriverPath().
   1219   @retval EFI_NOT_FOUND            A driver override for ControllerHandle was not
   1220                                    found.
   1221   @retval EFI_UNSUPPORTED          The operation is not supported.
   1222   @retval EFI_SUCCESS              The driver override for ControllerHandle was
   1223                                    returned in DriverImagePath.
   1224 
   1225 **/
   1226 EFI_STATUS
   1227 EFIAPI
   1228 GetDriverFromMapping (
   1229   IN     EFI_HANDLE                                     ControllerHandle,
   1230   IN OUT EFI_HANDLE                                     *DriverImageHandle,
   1231   IN     LIST_ENTRY                                     *MappingDataBase,
   1232   IN     EFI_HANDLE                                     CallerImageHandle
   1233   )
   1234 {
   1235   EFI_STATUS                  Status;
   1236   EFI_DEVICE_PATH_PROTOCOL    *ControllerDevicePath;
   1237   BOOLEAN                     ControllerFound;
   1238   BOOLEAN                     ImageFound;
   1239   EFI_HANDLE                  *ImageHandleBuffer;
   1240   UINTN                       ImageHandleCount;
   1241   UINTN                       Index;
   1242   EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
   1243   EFI_HANDLE                  DriverBindingHandle;
   1244   BOOLEAN                     FoundLastReturned;
   1245   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
   1246   DRIVER_IMAGE_INFO           *DriverImageInfo;
   1247   LIST_ENTRY                  *OverrideItemListIndex;
   1248   LIST_ENTRY                  *ImageInfoListIndex;
   1249   EFI_DEVICE_PATH_PROTOCOL    *TempDriverImagePath;
   1250   EFI_HANDLE                  ImageHandle;
   1251   EFI_HANDLE                  Handle;
   1252   EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;
   1253   EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
   1254   UINTN                       DevicePathSize;
   1255 
   1256   //
   1257   // Check that ControllerHandle is a valid handle
   1258   //
   1259   if (ControllerHandle == NULL) {
   1260     return EFI_INVALID_PARAMETER;
   1261   }
   1262   //
   1263   // Get the device path of ControllerHandle
   1264   //
   1265   Status = gBS->HandleProtocol (
   1266                   ControllerHandle,
   1267                   &gEfiDevicePathProtocolGuid,
   1268                   (VOID **) &ControllerDevicePath
   1269                   );
   1270   if (EFI_ERROR (Status) || ControllerDevicePath == NULL) {
   1271     return EFI_INVALID_PARAMETER;
   1272   }
   1273 
   1274   //
   1275   // Search ControllerDevicePath in MappingDataBase
   1276   //
   1277   OverrideItem = NULL;
   1278   ControllerFound = FALSE;
   1279   DevicePathSize = GetDevicePathSize (ControllerDevicePath);
   1280 
   1281   OverrideItemListIndex = GetFirstNode (MappingDataBase);
   1282   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
   1283     OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
   1284     if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
   1285       if (CompareMem (
   1286             ControllerDevicePath,
   1287             OverrideItem->ControllerDevicePath,
   1288             DevicePathSize
   1289             ) == 0
   1290           ) {
   1291         ControllerFound = TRUE;
   1292         break;
   1293       }
   1294     }
   1295     OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
   1296   }
   1297 
   1298   if (!ControllerFound) {
   1299     return EFI_NOT_FOUND;
   1300   }
   1301   //
   1302   // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
   1303   // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
   1304   //
   1305   if (*DriverImageHandle != NULL) {
   1306     if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) {
   1307       return EFI_INVALID_PARAMETER;
   1308     }
   1309   }
   1310   //
   1311   // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
   1312   //  so should check whether there is a dead loop.
   1313   //  Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
   1314   //  and check the controller device path whether appear again during the GetDriverPath() call.
   1315   //
   1316   if (CheckExistInStack (OverrideItem->ControllerDevicePath)) {
   1317     //
   1318     // There is a dependency dead loop if the ControllerDevicePath appear in stack twice
   1319     //
   1320     return EFI_UNSUPPORTED;
   1321   }
   1322   PushDevPathStack (OverrideItem->ControllerDevicePath);
   1323 
   1324   //
   1325   // Check every override driver, try to load and start them
   1326   //
   1327   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1328   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1329     DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
   1330     if (DriverImageInfo->ImageHandle == NULL) {
   1331       //
   1332       // Skip if the image is unloadable or unstartable
   1333       //
   1334       if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) {
   1335         TempDriverImagePath = DriverImageInfo->DriverImagePath;
   1336         //
   1337         // If the image device path contains an FV node, check the FV file device path is valid.
   1338         // If it is invalid, try to return the valid device path.
   1339         // FV address maybe changes for memory layout adjust from time to time,
   1340         // use this function could promise the FV file device path is right.
   1341         //
   1342         Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle);
   1343         if (!EFI_ERROR (Status)) {
   1344           FreePool (DriverImageInfo->DriverImagePath);
   1345           DriverImageInfo->DriverImagePath = TempDriverImagePath;
   1346         }
   1347         //
   1348         // Get all Loaded Image protocol to check whether the driver image has been loaded and started
   1349         //
   1350         ImageFound = FALSE;
   1351         ImageHandleCount  = 0;
   1352         Status = gBS->LocateHandleBuffer (
   1353                         ByProtocol,
   1354                         &gEfiLoadedImageProtocolGuid,
   1355                         NULL,
   1356                         &ImageHandleCount,
   1357                         &ImageHandleBuffer
   1358                         );
   1359         if (EFI_ERROR (Status) || (ImageHandleCount == 0)) {
   1360           return EFI_NOT_FOUND;
   1361         }
   1362 
   1363         for(Index = 0; Index < ImageHandleCount; Index ++) {
   1364           //
   1365           // Get the EFI Loaded Image Device Path Protocol
   1366           //
   1367           LoadedImageDevicePath = NULL;
   1368           Status = gBS->HandleProtocol (
   1369                           ImageHandleBuffer[Index],
   1370                           &gEfiLoadedImageDevicePathProtocolGuid,
   1371                           (VOID **) &LoadedImageDevicePath
   1372                           );
   1373           if (EFI_ERROR (Status)) {
   1374             //
   1375             // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
   1376             //
   1377             continue;
   1378           }
   1379 
   1380           DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
   1381           if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) {
   1382             if (CompareMem (
   1383                   DriverImageInfo->DriverImagePath,
   1384                   LoadedImageDevicePath,
   1385                   GetDevicePathSize (LoadedImageDevicePath)
   1386                   ) == 0
   1387                 ) {
   1388               ImageFound = TRUE;
   1389               break;
   1390             }
   1391           }
   1392         }
   1393 
   1394         if (ImageFound) {
   1395           //
   1396           // Find its related driver binding protocol
   1397           // Driver binding handle may be different with its driver's Image Handle.
   1398           //
   1399           DriverBindingHandle = NULL;
   1400           DriverBinding = GetBindingProtocolFromImageHandle (
   1401                             ImageHandleBuffer[Index],
   1402                             &DriverBindingHandle
   1403                             );
   1404           ASSERT (DriverBinding != NULL);
   1405           DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];
   1406         } else if (GetCurrentTpl() <= TPL_CALLBACK){
   1407           //
   1408           // The driver image has not been loaded and started. Try to load and start it now.
   1409           // Try to connect all device in the driver image path.
   1410           //
   1411           // Note: LoadImage() and  StartImage() should be called under CALLBACK TPL in theory, but
   1412           // since many device need to be connected in  CALLBACK level environment( e.g. Usb devices )
   1413           // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
   1414           // to use LoadImage() and  StartImage() in CALLBACK TPL.
   1415           //
   1416           Status = ConnectDevicePath (DriverImageInfo->DriverImagePath);
   1417           //
   1418           // check whether it points to a PCI Option Rom image,
   1419           // and try to use bus override protocol to get its first option rom image driver
   1420           //
   1421           TempDriverImagePath = DriverImageInfo->DriverImagePath;
   1422           gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
   1423           //
   1424           // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
   1425           //
   1426           Status = gBS->HandleProtocol(
   1427                           Handle,
   1428                           &gEfiBusSpecificDriverOverrideProtocolGuid,
   1429                           (VOID **) &BusSpecificDriverOverride
   1430                           );
   1431           if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
   1432             ImageHandle = NULL;
   1433             Status = BusSpecificDriverOverride->GetDriver (
   1434                                                   BusSpecificDriverOverride,
   1435                                                   &ImageHandle
   1436                                                   );
   1437             if (!EFI_ERROR (Status)) {
   1438               //
   1439               // Find its related driver binding protocol
   1440               // Driver binding handle may be different with its driver's Image handle
   1441               //
   1442               DriverBindingHandle = NULL;
   1443               DriverBinding = GetBindingProtocolFromImageHandle (
   1444                                 ImageHandle,
   1445                                 &DriverBindingHandle
   1446                                 );
   1447               ASSERT (DriverBinding != NULL);
   1448               DriverImageInfo->ImageHandle = ImageHandle;
   1449             }
   1450           }
   1451           //
   1452           // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
   1453           // Only file path media or FwVol Device Path Node remain if all device is connected
   1454           //
   1455           TempDriverImagePath = DriverImageInfo->DriverImagePath;
   1456           gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
   1457           if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) &&
   1458                (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) ||
   1459               (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL)
   1460              ) {
   1461             //
   1462             // Try to load the driver
   1463             //
   1464             TempDriverImagePath = DriverImageInfo->DriverImagePath;
   1465             Status = gBS->LoadImage (
   1466                             FALSE,
   1467                             CallerImageHandle,
   1468                             TempDriverImagePath,
   1469                             NULL,
   1470                             0,
   1471                             &ImageHandle
   1472                             );
   1473             if (!EFI_ERROR (Status)) {
   1474               //
   1475               // Try to start the driver
   1476               //
   1477               Status = gBS->StartImage (ImageHandle, NULL, NULL);
   1478               if (EFI_ERROR (Status)){
   1479                 DriverImageInfo->UnStartable = TRUE;
   1480                 DriverImageInfo->ImageHandle = NULL;
   1481               } else {
   1482                 //
   1483                 // Find its related driver binding protocol
   1484                 // Driver binding handle may be different with its driver's Image handle
   1485                 //
   1486                 DriverBindingHandle = NULL;
   1487                 DriverBinding = GetBindingProtocolFromImageHandle (
   1488                                    ImageHandle,
   1489                                    &DriverBindingHandle
   1490                                    );
   1491                 ASSERT (DriverBinding != NULL);
   1492                 DriverImageInfo->ImageHandle = ImageHandle;
   1493               }
   1494             } else {
   1495               DriverImageInfo->UnLoadable = TRUE;
   1496               DriverImageInfo->ImageHandle = NULL;
   1497             }
   1498           }
   1499         }
   1500         FreePool (ImageHandleBuffer);
   1501       }
   1502     }
   1503     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1504   }
   1505   //
   1506   // Finish try to load and start the override driver of a controller, popup the controller's device path
   1507   //
   1508   PopDevPathStack (NULL);
   1509 
   1510   //
   1511   // return the DriverImageHandle for ControllerHandle
   1512   //
   1513   FoundLastReturned = FALSE;
   1514   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1515   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1516     DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
   1517     if (DriverImageInfo->ImageHandle != NULL) {
   1518       if ((*DriverImageHandle == NULL) || FoundLastReturned) {
   1519         //
   1520         // If DriverImageHandle is NULL, then we just need to return the first driver.
   1521         // If FoundLastReturned, this means we have just encountered the previously returned driver.
   1522         // For both cases, we just return the image handle of this driver.
   1523         //
   1524         OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;
   1525         *DriverImageHandle = DriverImageInfo->ImageHandle;
   1526         return EFI_SUCCESS;
   1527       } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){
   1528         //
   1529         // We have found the previously returned driver.
   1530         //
   1531         FoundLastReturned = TRUE;
   1532       }
   1533     }
   1534     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1535   }
   1536 
   1537   return EFI_NOT_FOUND;
   1538 }
   1539 
   1540 
   1541 /**
   1542   Check mapping database whether already has the mapping info which
   1543   records the input Controller to input DriverImage.
   1544 
   1545   @param  ControllerDevicePath     The controller device path is to be check.
   1546   @param  DriverImageDevicePath    The driver image device path is to be check.
   1547   @param  MappingDataBase          Mapping database list entry pointer
   1548   @param  DriverInfoNum            the controller's total override driver number
   1549   @param  DriverImageNO            The driver order number for the input DriverImage.
   1550                                    If the DriverImageDevicePath is NULL, DriverImageNO is not set.
   1551 
   1552   @retval EFI_INVALID_PARAMETER    ControllerDevicePath or MappingDataBase is NULL.
   1553   @retval EFI_NOT_FOUND            ControllerDevicePath is not found in MappingDataBase or
   1554                                    DriverImageDevicePath is not found in the found DriverImage Info list.
   1555   @retval EFI_SUCCESS              The controller's total override driver number and
   1556                                    input DriverImage's order number is correctly return.
   1557 **/
   1558 EFI_STATUS
   1559 EFIAPI
   1560 CheckMapping (
   1561   IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
   1562   IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath  OPTIONAL,
   1563   IN     LIST_ENTRY                                     *MappingDataBase,
   1564   OUT    UINT32                                         *DriverInfoNum  OPTIONAL,
   1565   OUT    UINT32                                         *DriverImageNO  OPTIONAL
   1566   )
   1567 {
   1568   LIST_ENTRY                  *OverrideItemListIndex;
   1569   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
   1570   LIST_ENTRY                  *ImageInfoListIndex;
   1571   DRIVER_IMAGE_INFO           *DriverImageInfo;
   1572   BOOLEAN                     Found;
   1573   UINT32                      ImageNO;
   1574   UINTN                       DevicePathSize;
   1575 
   1576   if (ControllerDevicePath == NULL) {
   1577     return EFI_INVALID_PARAMETER;
   1578   }
   1579   if (MappingDataBase == NULL) {
   1580     return EFI_INVALID_PARAMETER;
   1581   }
   1582 
   1583   //
   1584   // Search ControllerDevicePath in MappingDataBase
   1585   //
   1586   Found = FALSE;
   1587   OverrideItem = NULL;
   1588   OverrideItemListIndex = GetFirstNode (MappingDataBase);
   1589   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
   1590     OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
   1591     DevicePathSize = GetDevicePathSize (ControllerDevicePath);
   1592     if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
   1593       if (CompareMem (
   1594             ControllerDevicePath,
   1595             OverrideItem->ControllerDevicePath,
   1596             DevicePathSize
   1597             ) == 0
   1598           ) {
   1599         Found = TRUE;
   1600         break;
   1601       }
   1602     }
   1603     OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
   1604   }
   1605 
   1606   if (!Found) {
   1607     //
   1608     // ControllerDevicePath is not in MappingDataBase
   1609     //
   1610     return EFI_NOT_FOUND;
   1611   }
   1612 
   1613   ASSERT (OverrideItem->DriverInfoNum != 0);
   1614   if (DriverInfoNum != NULL) {
   1615     *DriverInfoNum = OverrideItem->DriverInfoNum;
   1616   }
   1617 
   1618   //
   1619   // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
   1620   // in the controller's Driver Image Info List
   1621   //
   1622   if (DriverImageDevicePath == NULL) {
   1623     return EFI_SUCCESS;
   1624   }
   1625   //
   1626   // return the DriverImageHandle for ControllerHandle
   1627   //
   1628   ImageNO = 0;
   1629   Found = FALSE;
   1630   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1631   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1632     DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
   1633     ImageNO++;
   1634     DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
   1635     if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
   1636       if (CompareMem (
   1637             DriverImageDevicePath,
   1638             DriverImageInfo->DriverImagePath,
   1639             GetDevicePathSize (DriverImageInfo->DriverImagePath)
   1640             ) == 0
   1641           ) {
   1642         Found = TRUE;
   1643         break;
   1644       }
   1645     }
   1646     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1647   }
   1648 
   1649   if (!Found) {
   1650     //
   1651     // DriverImageDevicePath is not found in the controller's Driver Image Info List
   1652     //
   1653     return EFI_NOT_FOUND;
   1654   } else {
   1655     if (DriverImageNO != NULL) {
   1656       *DriverImageNO = ImageNO;
   1657     }
   1658     return EFI_SUCCESS;
   1659   }
   1660 }
   1661 
   1662 
   1663 /**
   1664   Insert a driver image as a controller's override driver into the mapping database.
   1665   The driver image's order number is indicated by DriverImageNO.
   1666 
   1667   @param  ControllerDevicePath     The controller device path need to add a
   1668                                    override driver image item
   1669   @param  DriverImageDevicePath    The driver image device path need to be insert
   1670   @param  MappingDataBase          Mapping database list entry pointer
   1671   @param  DriverImageNO            The inserted order number. If this number is taken,
   1672                                    the larger available number will be used.
   1673 
   1674   @retval EFI_INVALID_PARAMETER    ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
   1675                                    or MappingDataBase is NULL
   1676   @retval EFI_ALREADY_STARTED      The input Controller to input DriverImage has been
   1677                                    recorded into the mapping database.
   1678   @retval EFI_SUCCESS              The Controller and DriverImage are inserted into
   1679                                    the mapping database successfully.
   1680 
   1681 **/
   1682 EFI_STATUS
   1683 EFIAPI
   1684 InsertDriverImage (
   1685   IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
   1686   IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath,
   1687   IN     LIST_ENTRY                                     *MappingDataBase,
   1688   IN     UINT32                                         DriverImageNO
   1689   )
   1690 {
   1691   EFI_STATUS                  Status;
   1692   LIST_ENTRY                  *OverrideItemListIndex;
   1693   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
   1694   LIST_ENTRY                  *ImageInfoListIndex;
   1695   DRIVER_IMAGE_INFO           *DriverImageInfo;
   1696   BOOLEAN                     Found;
   1697   UINT32                      ImageNO;
   1698   UINTN                       DevicePathSize;
   1699 
   1700   if (ControllerDevicePath == NULL) {
   1701     return EFI_INVALID_PARAMETER;
   1702   }
   1703   if (DriverImageDevicePath == NULL) {
   1704     return EFI_INVALID_PARAMETER;
   1705   }
   1706   if (MappingDataBase == NULL) {
   1707     return EFI_INVALID_PARAMETER;
   1708   }
   1709 
   1710   //
   1711   // If the driver is already in the controller's Driver Image Info List,
   1712   // just return EFI_ALREADY_STARTED.
   1713   //
   1714   Status = CheckMapping (
   1715              ControllerDevicePath,
   1716              DriverImageDevicePath,
   1717              MappingDataBase,
   1718              NULL,
   1719              NULL
   1720              );
   1721   if (Status == EFI_SUCCESS) {
   1722     return EFI_ALREADY_STARTED;
   1723   }
   1724 
   1725   //
   1726   // Search the input ControllerDevicePath in MappingDataBase
   1727   //
   1728   Found = FALSE;
   1729   OverrideItem = NULL;
   1730   OverrideItemListIndex = GetFirstNode (MappingDataBase);
   1731   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
   1732     OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
   1733     DevicePathSize = GetDevicePathSize (ControllerDevicePath);
   1734     if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
   1735       if (CompareMem (
   1736             ControllerDevicePath,
   1737             OverrideItem->ControllerDevicePath,
   1738             DevicePathSize
   1739             ) == 0
   1740           ) {
   1741         Found = TRUE;
   1742         break;
   1743       }
   1744     }
   1745     OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
   1746   }
   1747   //
   1748   // If cannot find, this is a new controller item
   1749   // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
   1750   //
   1751   if (!Found) {
   1752     OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
   1753     ASSERT (OverrideItem != NULL);
   1754     OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
   1755     OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
   1756     InitializeListHead (&OverrideItem->DriverInfoList);
   1757     InsertTailList (MappingDataBase, &OverrideItem->Link);
   1758   }
   1759 
   1760   //
   1761   // Prepare the driver image related DRIVER_IMAGE_INFO structure.
   1762   //
   1763   DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
   1764   ASSERT (DriverImageInfo != NULL);
   1765   DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
   1766   DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath);
   1767   //
   1768   // Find the driver image wanted order location
   1769   //
   1770   ImageNO = 0;
   1771   Found = FALSE;
   1772   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1773   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1774     if (ImageNO == (DriverImageNO - 1)) {
   1775       //
   1776       // find the wanted order location, insert it
   1777       //
   1778       InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);
   1779       OverrideItem->DriverInfoNum ++;
   1780       Found = TRUE;
   1781       break;
   1782     }
   1783     ImageNO++;
   1784     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1785   }
   1786 
   1787   if (!Found) {
   1788     //
   1789     // if not find the wanted order location, add it as last item of the controller mapping item
   1790     //
   1791     InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
   1792     OverrideItem->DriverInfoNum ++;
   1793   }
   1794 
   1795   return EFI_SUCCESS;
   1796 }
   1797 
   1798 
   1799 /**
   1800   Delete a controller's override driver from the mapping database.
   1801 
   1802   @param  ControllerDevicePath     The controller device path will be deleted
   1803                                    when all drivers images on it are removed.
   1804   @param  DriverImageDevicePath    The driver image device path will be delete.
   1805                                    If NULL, all driver image will be delete.
   1806   @param  MappingDataBase          Mapping database list entry pointer
   1807 
   1808   @retval EFI_INVALID_PARAMETER    ControllerDevicePath is NULL, or MappingDataBase is NULL
   1809   @retval EFI_NOT_FOUND            ControllerDevicePath is not found in MappingDataBase or
   1810                                    DriverImageDevicePath is not found in the found DriverImage Info list.
   1811   @retval EFI_SUCCESS              Delete the specified driver successfully.
   1812 
   1813 **/
   1814 EFI_STATUS
   1815 EFIAPI
   1816 DeleteDriverImage (
   1817   IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
   1818   IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath,
   1819   IN     LIST_ENTRY                                     *MappingDataBase
   1820   )
   1821 {
   1822   EFI_STATUS                  Status;
   1823   LIST_ENTRY                  *OverrideItemListIndex;
   1824   PLATFORM_OVERRIDE_ITEM      *OverrideItem;
   1825   LIST_ENTRY                  *ImageInfoListIndex;
   1826   DRIVER_IMAGE_INFO           *DriverImageInfo;
   1827   BOOLEAN                     Found;
   1828   UINTN                       DevicePathSize;
   1829 
   1830   if (ControllerDevicePath == NULL) {
   1831     return EFI_INVALID_PARAMETER;
   1832   }
   1833 
   1834   if (MappingDataBase == NULL) {
   1835     return EFI_INVALID_PARAMETER;
   1836   }
   1837 
   1838   //
   1839   // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
   1840   //
   1841   Status = CheckMapping (
   1842              ControllerDevicePath,
   1843              DriverImageDevicePath,
   1844              MappingDataBase,
   1845              NULL,
   1846              NULL
   1847              );
   1848   if (EFI_ERROR (Status)) {
   1849     return EFI_NOT_FOUND;
   1850   }
   1851 
   1852   //
   1853   // Search ControllerDevicePath in MappingDataBase
   1854   //
   1855   Found = FALSE;
   1856   OverrideItem = NULL;
   1857   OverrideItemListIndex = GetFirstNode (MappingDataBase);
   1858   while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
   1859     OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
   1860     DevicePathSize = GetDevicePathSize (ControllerDevicePath);
   1861     if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
   1862       if (CompareMem (
   1863             ControllerDevicePath,
   1864             OverrideItem->ControllerDevicePath,
   1865             DevicePathSize
   1866             ) == 0
   1867           ) {
   1868         Found = TRUE;
   1869         break;
   1870       }
   1871     }
   1872     OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
   1873   }
   1874 
   1875   ASSERT (Found);
   1876   ASSERT (OverrideItem->DriverInfoNum != 0);
   1877 
   1878   Found = FALSE;
   1879   ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
   1880   while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
   1881     DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
   1882     ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
   1883     if (DriverImageDevicePath != NULL) {
   1884       //
   1885       // Search for the specified DriverImageDevicePath and remove it, then break.
   1886       //
   1887       DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
   1888       if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
   1889         if (CompareMem (
   1890               DriverImageDevicePath,
   1891               DriverImageInfo->DriverImagePath,
   1892               GetDevicePathSize (DriverImageInfo->DriverImagePath)
   1893               ) == 0
   1894             ) {
   1895           Found = TRUE;
   1896           FreePool(DriverImageInfo->DriverImagePath);
   1897           RemoveEntryList (&DriverImageInfo->Link);
   1898           OverrideItem->DriverInfoNum --;
   1899           break;
   1900         }
   1901       }
   1902     } else {
   1903       //
   1904       // Remove all existing driver image info entries, so no break here.
   1905       //
   1906       Found = TRUE;
   1907       FreePool(DriverImageInfo->DriverImagePath);
   1908       RemoveEntryList (&DriverImageInfo->Link);
   1909       OverrideItem->DriverInfoNum --;
   1910     }
   1911   }
   1912 
   1913   //
   1914   // Confirm all driver image info entries have been removed,
   1915   // if DriverImageDevicePath is NULL.
   1916   //
   1917   if (DriverImageDevicePath == NULL) {
   1918     ASSERT (OverrideItem->DriverInfoNum == 0);
   1919   }
   1920   //
   1921   // If Override Item has no driver image info entry, then delete this item.
   1922   //
   1923   if (OverrideItem->DriverInfoNum == 0) {
   1924     FreePool(OverrideItem->ControllerDevicePath);
   1925     RemoveEntryList (&OverrideItem->Link);
   1926     FreePool (OverrideItem);
   1927   }
   1928 
   1929   if (!Found) {
   1930     //
   1931     // DriverImageDevicePath is not NULL and cannot be found in the controller's
   1932     // driver image info list.
   1933     //
   1934     return EFI_NOT_FOUND;
   1935   }
   1936 
   1937   return EFI_SUCCESS;
   1938 }
   1939