PlatDriOverrideLib.c revision 32c412666889578b8b1e1e08674506796fba1153
1/** @file
2  Implementation of the shared functions to do the platform driver vverride mapping.
3
4  Copyright (c) 2007 - 2009, Intel Corporation
5  All rights reserved. This program and the accompanying materials
6  are licensed and made available under the terms and conditions of the BSD License
7  which accompanies this distribution.  The full text of the license may be found at
8  http://opensource.org/licenses/bsd-license.php
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')
31typedef 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')
41typedef 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
48LIST_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**/
58EFI_STATUS
59EFIAPI
60PushDevPathStack (
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**/
84EFI_STATUS
85EFIAPI
86PopDevPathStack (
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**/
120BOOLEAN
121EFIAPI
122CheckExistInStack (
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 funciton
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**/
168EFI_STATUS
169EFIAPI
170UpdateFvFileDevicePath (
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**/
388VOID *
389EFIAPI
390GetVariableAndSize (
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**/
446EFI_STATUS
447EFIAPI
448ConnectDevicePath (
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**/
559EFI_STATUS
560EFIAPI
561FreeMappingDatabase (
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**/
655EFI_STATUS
656EFIAPI
657InitOverridesMapping (
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  do {
695    VariableIndex = VariableBuffer;
696    //
697    // End flag
698    //
699    NotEnd = *(UINT32*) VariableIndex;
700    //
701    // Traverse the entries containing the mapping that Controller Device Path
702    // to a set of Driver Device Paths within this variable.
703    //
704    VariableIndex = VariableIndex + sizeof (UINT32);
705    while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) {
706      //
707      // Check signature of this entry
708      //
709      Signature = *(UINT32 *) VariableIndex;
710      if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) {
711        Corrupted = TRUE;
712        break;
713      }
714      //
715      // Create PLATFORM_OVERRIDE_ITEM for this mapping
716      //
717      OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
718      ASSERT (OverrideItem != NULL);
719      OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
720      InitializeListHead (&OverrideItem->DriverInfoList);
721      VariableIndex = VariableIndex + sizeof (UINT32);
722      //
723      // Get DriverNum
724      //
725      DriverNumber = *(UINT32*) VariableIndex;
726      OverrideItem->DriverInfoNum = DriverNumber;
727      VariableIndex = VariableIndex + sizeof (UINT32);
728      //
729      // Get ControllerDevicePath[]
730      //
731      ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
732      OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
733      VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath);
734      //
735      // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()
736      //
737      VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
738
739      //
740      // Get all DriverImageDevicePath[]
741      //
742      for (Index = 0; Index < DriverNumber; Index++) {
743        //
744        // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]
745        //
746        DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
747        ASSERT (DriverImageInfo != NULL);
748        DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
749
750        DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;
751        DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath);
752        VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath);
753        //
754        // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()
755        //
756        VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
757
758        InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
759      }
760      InsertTailList (MappingDataBase, &OverrideItem->Link);
761    }
762
763    FreePool (VariableBuffer);
764    if (Corrupted) {
765      FreeMappingDatabase (MappingDataBase);
766      return EFI_VOLUME_CORRUPTED;
767    }
768
769    //
770    // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.
771    // NotEnd indicates whether current variable is the end variable.
772    //
773    if (NotEnd != 0) {
774      UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++);
775      VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
776      ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
777      if (VariableBuffer == NULL) {
778        FreeMappingDatabase (MappingDataBase);
779        return EFI_VOLUME_CORRUPTED;
780      }
781    }
782
783  } while (NotEnd != 0);
784
785  return EFI_SUCCESS;
786}
787
788
789/**
790  Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.
791
792  @param  OverrideItemListIndex    Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM
793
794  @return The needed size number
795
796**/
797UINTN
798EFIAPI
799GetOneItemNeededSize (
800  IN  LIST_ENTRY            *OverrideItemListIndex
801  )
802{
803  UINTN                       NeededSize;
804  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
805  LIST_ENTRY                  *ImageInfoListIndex;
806  DRIVER_IMAGE_INFO           *DriverImageInfo;
807  UINTN                       DevicePathSize;
808
809  NeededSize = 0;
810  OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
811  NeededSize += sizeof (UINT32); //UINT32  SIGNATURE;
812  NeededSize += sizeof (UINT32); //UINT32  DriverNum;
813  DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath);
814  NeededSize += DevicePathSize; // ControllerDevicePath
815  //
816  // Align the controller device path
817  //
818  NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
819  //
820  // Traverse the Driver Info List of this Override Item
821  //
822  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
823  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
824    DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
825    DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
826    NeededSize += DevicePathSize; //DriverDevicePath
827    //
828    // Align the driver image device path
829    //
830    NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));
831    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
832  }
833
834  return NeededSize;
835}
836
837/**
838  Deletes all environment variable(s) that contain the override mappings from Controller Device Path to
839  a set of Driver Device Paths.
840
841  @retval EFI_SUCCESS  Delete all variable(s) successfully.
842
843**/
844EFI_STATUS
845EFIAPI
846DeleteOverridesVariables (
847  VOID
848  )
849{
850  EFI_STATUS                  Status;
851  VOID                        *VariableBuffer;
852  UINTN                       VariableNum;
853  UINTN                       BufferSize;
854  UINTN                       Index;
855  CHAR16                      OverrideVariableName[40];
856
857  //
858  // Get environment variable(s) number
859  //
860  VariableNum = 0;
861  VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);
862  VariableNum++;
863  if (VariableBuffer == NULL) {
864    return EFI_NOT_FOUND;
865  }
866  //
867  // Check NotEnd to get all PlatDriOverX variable(s)
868  //
869  while ((*(UINT32*)VariableBuffer) != 0) {
870    UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);
871    VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);
872    VariableNum++;
873    ASSERT (VariableBuffer != NULL);
874  }
875
876  //
877  // Delete PlatDriOver and all additional variables, if exist.
878  //
879  Status = gRT->SetVariable (
880                  L"PlatDriOver",
881                  &gEfiCallerIdGuid,
882                  EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
883                  0,
884                  NULL
885                  );
886  ASSERT (!EFI_ERROR (Status));
887  for (Index = 1; Index < VariableNum; Index++) {
888    UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index);
889    Status = gRT->SetVariable (
890                    OverrideVariableName,
891                    &gEfiCallerIdGuid,
892                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
893                    0,
894                    NULL
895                    );
896    ASSERT (!EFI_ERROR (Status));
897  }
898  return EFI_SUCCESS;
899}
900
901
902/**
903  Save the memory mapping database into NV environment variable(s).
904
905  @param  MappingDataBase          Mapping database list entry pointer
906
907  @retval EFI_SUCCESS              Save memory mapping database successfully
908  @retval EFI_INVALID_PARAMETER    MappingDataBase pointer is null
909
910**/
911EFI_STATUS
912EFIAPI
913SaveOverridesMapping (
914  IN  LIST_ENTRY              *MappingDataBase
915  )
916{
917  EFI_STATUS                  Status;
918  VOID                        *VariableBuffer;
919  UINT8                       *VariableIndex;
920  UINTN                       NumIndex;
921  CHAR16                      OverrideVariableName[40];
922  UINT32                      NotEnd;
923  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
924  DRIVER_IMAGE_INFO           *DriverImageInfo;
925  LIST_ENTRY                  *OverrideItemListIndex;
926  LIST_ENTRY                  *ItemIndex;
927  LIST_ENTRY                  *ImageInfoListIndex;
928  UINTN                       VariableNeededSize;
929  UINT64                      MaximumVariableStorageSize;
930  UINT64                      RemainingVariableStorageSize;
931  UINT64                      MaximumVariableSize;
932  UINTN                       OneItemNeededSize;
933
934  if (MappingDataBase == NULL) {
935    return EFI_INVALID_PARAMETER;
936  }
937
938  if (IsListEmpty (MappingDataBase)) {
939    Status = DeleteOverridesVariables ();
940    return EFI_SUCCESS;
941  }
942
943  //
944  // Get the the maximum size of an individual EFI variable in current system
945  //
946  gRT->QueryVariableInfo (
947          EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
948          &MaximumVariableStorageSize,
949          &RemainingVariableStorageSize,
950          &MaximumVariableSize
951          );
952
953  NumIndex = 0;
954  OverrideItemListIndex = GetFirstNode (MappingDataBase);
955  while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
956    //
957    // Try to find the most proper variable size which <= MaximumVariableSize,
958    // but can contain mapping info as much as possible
959    //
960    VariableNeededSize = sizeof (UINT32); // NotEnd;
961    ItemIndex = OverrideItemListIndex;
962    NotEnd = FALSE;
963    //
964    // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.
965    //
966    while (!IsNull (MappingDataBase, ItemIndex)) {
967      OneItemNeededSize = GetOneItemNeededSize (ItemIndex);
968      //
969      // If the total size exceeds the MaximumVariableSize, then we must use
970      // multiple variables.
971      //
972      if ((VariableNeededSize +
973           OneItemNeededSize +
974           sizeof (VARIABLE_HEADER) +
975           StrSize (L"PlatDriOver ")
976           ) >= MaximumVariableSize
977          ) {
978        NotEnd = TRUE;
979        break;
980      }
981
982      VariableNeededSize += OneItemNeededSize;
983      ItemIndex = GetNextNode (MappingDataBase, ItemIndex);
984    }
985
986    if (NotEnd != 0) {
987      if (VariableNeededSize == sizeof (UINT32)) {
988        //
989        // If an individual EFI variable cannot contain a single Item, return error
990        //
991        return EFI_OUT_OF_RESOURCES;
992      }
993    }
994
995    //
996    // VariableNeededSize is the most proper variable size, allocate variable buffer
997    // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
998    //
999    VariableBuffer = AllocateZeroPool (VariableNeededSize);
1000    ASSERT (VariableBuffer != NULL);
1001    ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);
1002
1003    //
1004    // Fill the variable buffer according to MappingDataBase
1005    //
1006    VariableIndex = VariableBuffer;
1007    *(UINT32 *) VariableIndex = NotEnd;
1008    VariableIndex += sizeof (UINT32); // pass NotEnd
1009    //
1010    // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize
1011    //
1012    while (OverrideItemListIndex != ItemIndex){
1013      *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
1014      VariableIndex += sizeof (UINT32); // pass SIGNATURE
1015
1016      OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
1017      *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum;
1018      VariableIndex += sizeof (UINT32); // pass DriverNum
1019
1020      CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath));
1021      VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath
1022
1023      //
1024      // Align the VariableIndex since the controller device path may not be aligned
1025      //
1026      VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
1027      //
1028      // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM
1029      //
1030      ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1031      while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1032        DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
1033        CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath));
1034        VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath
1035        //
1036        // Align the VariableIndex since the driver image device path may not be aligned
1037        //
1038        VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));
1039        ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1040      }
1041
1042      OverrideItemListIndex =  GetNextNode (MappingDataBase, OverrideItemListIndex);
1043    }
1044
1045    ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize);
1046
1047    if (NumIndex == 0) {
1048      UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver");
1049    } else {
1050      UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex );
1051    }
1052
1053    Status = gRT->SetVariable (
1054                    OverrideVariableName,
1055                    &gEfiCallerIdGuid,
1056                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
1057                    VariableNeededSize,
1058                    VariableBuffer
1059                    );
1060    ASSERT (!EFI_ERROR(Status));
1061
1062    NumIndex ++;
1063    FreePool (VariableBuffer);
1064  }
1065
1066  return EFI_SUCCESS;
1067}
1068
1069/**
1070  Get the first Binding protocol which has the specific image handle.
1071
1072  @param  ImageHandle          The Image handle
1073  @param  BindingHandle        The BindingHandle of the found Driver Binding protocol.
1074                               If Binding protocol is not found, it is set to NULL.
1075
1076  @return                      Pointer into the Binding Protocol interface
1077  @retval NULL                 The paramter is not valid or the binding protocol is not found.
1078
1079**/
1080EFI_DRIVER_BINDING_PROTOCOL *
1081EFIAPI
1082GetBindingProtocolFromImageHandle (
1083  IN  EFI_HANDLE   ImageHandle,
1084  OUT EFI_HANDLE   *BindingHandle
1085  )
1086{
1087  EFI_STATUS                        Status;
1088  UINTN                             Index;
1089  UINTN                             DriverBindingHandleCount;
1090  EFI_HANDLE                        *DriverBindingHandleBuffer;
1091  EFI_DRIVER_BINDING_PROTOCOL       *DriverBindingInterface;
1092
1093  if (BindingHandle == NULL || ImageHandle == NULL) {
1094    return NULL;
1095  }
1096  //
1097  // Get all drivers which support driver binding protocol
1098  //
1099  DriverBindingHandleCount  = 0;
1100  Status = gBS->LocateHandleBuffer (
1101                  ByProtocol,
1102                  &gEfiDriverBindingProtocolGuid,
1103                  NULL,
1104                  &DriverBindingHandleCount,
1105                  &DriverBindingHandleBuffer
1106                  );
1107  if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {
1108    return NULL;
1109  }
1110
1111  for (Index = 0; Index < DriverBindingHandleCount; Index++) {
1112    DriverBindingInterface = NULL;
1113    Status = gBS->OpenProtocol (
1114                    DriverBindingHandleBuffer[Index],
1115                    &gEfiDriverBindingProtocolGuid,
1116                    (VOID **) &DriverBindingInterface,
1117                    NULL,
1118                    NULL,
1119                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
1120                    );
1121    if (EFI_ERROR (Status)) {
1122      continue;
1123    }
1124
1125    if (DriverBindingInterface->ImageHandle == ImageHandle) {
1126      *BindingHandle = DriverBindingHandleBuffer[Index];
1127      FreePool (DriverBindingHandleBuffer);
1128      return DriverBindingInterface;
1129    }
1130  }
1131
1132  //
1133  // If no Driver Binding Protocol instance is found
1134  //
1135  FreePool (DriverBindingHandleBuffer);
1136  *BindingHandle = NULL;
1137  return NULL;
1138}
1139
1140/**
1141  Return the current TPL.
1142
1143  @return Current TPL
1144
1145**/
1146EFI_TPL
1147GetCurrentTpl (
1148  VOID
1149  )
1150{
1151  EFI_TPL                 Tpl;
1152
1153  Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
1154  gBS->RestoreTPL (Tpl);
1155
1156  return Tpl;
1157}
1158
1159
1160/**
1161  Retrieves the image handle of the platform override driver for a controller in
1162  the system from the memory mapping database.
1163
1164  @param  ControllerHandle         The device handle of the controller to check if
1165                                   a driver override exists.
1166  @param  DriverImageHandle        On input, the previously returnd driver image handle.
1167                                   On output, a pointer to the next driver handle.
1168                                   Passing in a pointer to NULL, will return the
1169                                   first driver handle for ControllerHandle.
1170  @param  MappingDataBase          Mapping database list entry pointer
1171  @param  CallerImageHandle        The caller driver's image handle, for
1172                                   UpdateFvFileDevicePath use.
1173
1174  @retval EFI_INVALID_PARAMETER    The handle specified by ControllerHandle is not
1175                                   a valid handle.  Or DriverImagePath is not a
1176                                   device path that was returned on a previous call
1177                                   to GetDriverPath().
1178  @retval EFI_NOT_FOUND            A driver override for ControllerHandle was not
1179                                   found.
1180  @retval EFI_UNSUPPORTED          The operation is not supported.
1181  @retval EFI_SUCCESS              The driver override for ControllerHandle was
1182                                   returned in DriverImagePath.
1183
1184**/
1185EFI_STATUS
1186EFIAPI
1187GetDriverFromMapping (
1188  IN     EFI_HANDLE                                     ControllerHandle,
1189  IN OUT EFI_HANDLE                                     *DriverImageHandle,
1190  IN     LIST_ENTRY                                     *MappingDataBase,
1191  IN     EFI_HANDLE                                     CallerImageHandle
1192  )
1193{
1194  EFI_STATUS                  Status;
1195  EFI_DEVICE_PATH_PROTOCOL    *ControllerDevicePath;
1196  BOOLEAN                     ControllerFound;
1197  BOOLEAN                     ImageFound;
1198  EFI_HANDLE                  *ImageHandleBuffer;
1199  UINTN                       ImageHandleCount;
1200  UINTN                       Index;
1201  EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
1202  EFI_HANDLE                  DriverBindingHandle;
1203  BOOLEAN                     FoundLastReturned;
1204  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
1205  DRIVER_IMAGE_INFO           *DriverImageInfo;
1206  LIST_ENTRY                  *OverrideItemListIndex;
1207  LIST_ENTRY                  *ImageInfoListIndex;
1208  EFI_DEVICE_PATH_PROTOCOL    *TempDriverImagePath;
1209  EFI_HANDLE                  ImageHandle;
1210  EFI_HANDLE                  Handle;
1211  EFI_DEVICE_PATH_PROTOCOL    *LoadedImageDevicePath;
1212  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL  *BusSpecificDriverOverride;
1213  UINTN                       DevicePathSize;
1214
1215  //
1216  // Check that ControllerHandle is a valid handle
1217  //
1218  if (ControllerHandle == NULL) {
1219    return EFI_INVALID_PARAMETER;
1220  }
1221  //
1222  // Get the device path of ControllerHandle
1223  //
1224  Status = gBS->HandleProtocol (
1225                  ControllerHandle,
1226                  &gEfiDevicePathProtocolGuid,
1227                  (VOID **) &ControllerDevicePath
1228                  );
1229  if (EFI_ERROR (Status) || ControllerDevicePath == NULL) {
1230    return EFI_INVALID_PARAMETER;
1231  }
1232
1233  //
1234  // Search ControllerDevicePath in MappingDataBase
1235  //
1236  OverrideItem = NULL;
1237  ControllerFound = FALSE;
1238  DevicePathSize = GetDevicePathSize (ControllerDevicePath);
1239
1240  OverrideItemListIndex = GetFirstNode (MappingDataBase);
1241  while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
1242    OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
1243    if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
1244      if (CompareMem (
1245            ControllerDevicePath,
1246            OverrideItem->ControllerDevicePath,
1247            DevicePathSize
1248            ) == 0
1249          ) {
1250        ControllerFound = TRUE;
1251        break;
1252      }
1253    }
1254    OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
1255  }
1256
1257  if (!ControllerFound) {
1258    return EFI_NOT_FOUND;
1259  }
1260  //
1261  // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.
1262  // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().
1263  //
1264  if (*DriverImageHandle != NULL) {
1265    if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) {
1266      return EFI_INVALID_PARAMETER;
1267    }
1268  }
1269  //
1270  // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,
1271  //  so should check whether there is a dead loop.
1272  //  Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,
1273  //  and check the controller device path whether appear again during the GetDriverPath() call.
1274  //
1275  if (CheckExistInStack (OverrideItem->ControllerDevicePath)) {
1276    //
1277    // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice
1278    //
1279    return EFI_UNSUPPORTED;
1280  }
1281  PushDevPathStack (OverrideItem->ControllerDevicePath);
1282
1283  //
1284  // Check every override driver, try to load and start them
1285  //
1286  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1287  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1288    DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
1289    if (DriverImageInfo->ImageHandle == NULL) {
1290      //
1291      // Skip if the image is unloadable or unstartable
1292      //
1293      if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) {
1294        TempDriverImagePath = DriverImageInfo->DriverImagePath;
1295        //
1296        // If the image device path contains an FV node, check the FV file device path is valid.
1297        // If it is invalid, try to return the valid device path.
1298        // FV address maybe changes for memory layout adjust from time to time,
1299        // use this funciton could promise the FV file device path is right.
1300        //
1301        Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle);
1302        if (!EFI_ERROR (Status)) {
1303          FreePool (DriverImageInfo->DriverImagePath);
1304          DriverImageInfo->DriverImagePath = TempDriverImagePath;
1305        }
1306        //
1307        // Get all Loaded Image protocol to check whether the driver image has been loaded and started
1308        //
1309        ImageFound = FALSE;
1310        ImageHandleCount  = 0;
1311        Status = gBS->LocateHandleBuffer (
1312                        ByProtocol,
1313                        &gEfiLoadedImageProtocolGuid,
1314                        NULL,
1315                        &ImageHandleCount,
1316                        &ImageHandleBuffer
1317                        );
1318        if (EFI_ERROR (Status) || (ImageHandleCount == 0)) {
1319          return EFI_NOT_FOUND;
1320        }
1321
1322        for(Index = 0; Index < ImageHandleCount; Index ++) {
1323          //
1324          // Get the EFI Loaded Image Device Path Protocol
1325          //
1326          LoadedImageDevicePath = NULL;
1327          Status = gBS->HandleProtocol (
1328                          ImageHandleBuffer[Index],
1329                          &gEfiLoadedImageDevicePathProtocolGuid,
1330                          (VOID **) &LoadedImageDevicePath
1331                          );
1332          if (EFI_ERROR (Status)) {
1333            //
1334            // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.
1335            //
1336            continue;
1337          }
1338
1339          DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);
1340          if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) {
1341            if (CompareMem (
1342                  DriverImageInfo->DriverImagePath,
1343                  LoadedImageDevicePath,
1344                  GetDevicePathSize (LoadedImageDevicePath)
1345                  ) == 0
1346                ) {
1347              ImageFound = TRUE;
1348              break;
1349            }
1350          }
1351        }
1352
1353        if (ImageFound) {
1354          //
1355          // Find its related driver binding protocol
1356          // Driver binding handle may be different with its driver's Image Handle.
1357          //
1358          DriverBindingHandle = NULL;
1359          DriverBinding = GetBindingProtocolFromImageHandle (
1360                            ImageHandleBuffer[Index],
1361                            &DriverBindingHandle
1362                            );
1363          ASSERT (DriverBinding != NULL);
1364          DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];
1365        } else if (GetCurrentTpl() <= TPL_CALLBACK){
1366          //
1367          // The driver image has not been loaded and started. Try to load and start it now.
1368          // Try to connect all device in the driver image path.
1369          //
1370          // Note: LoadImage() and  StartImage() should be called under CALLBACK TPL in theory, but
1371          // since many device need to be connected in  CALLBACK level environment( e.g. Usb devices )
1372          // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit
1373          // to use LoadImage() and  StartImage() in CALLBACK TPL.
1374          //
1375          Status = ConnectDevicePath (DriverImageInfo->DriverImagePath);
1376          //
1377          // check whether it points to a PCI Option Rom image,
1378          // and try to use bus override protocol to get its first option rom image driver
1379          //
1380          TempDriverImagePath = DriverImageInfo->DriverImagePath;
1381          gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
1382          //
1383          // Get the Bus Specific Driver Override Protocol instance on the Controller Handle
1384          //
1385          Status = gBS->HandleProtocol(
1386                          Handle,
1387                          &gEfiBusSpecificDriverOverrideProtocolGuid,
1388                          (VOID **) &BusSpecificDriverOverride
1389                          );
1390          if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {
1391            ImageHandle = NULL;
1392            Status = BusSpecificDriverOverride->GetDriver (
1393                                                  BusSpecificDriverOverride,
1394                                                  &ImageHandle
1395                                                  );
1396            if (!EFI_ERROR (Status)) {
1397              //
1398              // Find its related driver binding protocol
1399              // Driver binding handle may be different with its driver's Image handle
1400              //
1401              DriverBindingHandle = NULL;
1402              DriverBinding = GetBindingProtocolFromImageHandle (
1403                                ImageHandle,
1404                                &DriverBindingHandle
1405                                );
1406              ASSERT (DriverBinding != NULL);
1407              DriverImageInfo->ImageHandle = ImageHandle;
1408            }
1409          }
1410          //
1411          // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.
1412          // Only file path media or FwVol Device Path Node remain if all device is connected
1413          //
1414          TempDriverImagePath = DriverImageInfo->DriverImagePath;
1415          gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);
1416          if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) &&
1417               (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) ||
1418              (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL)
1419             ) {
1420            //
1421            // Try to load the driver
1422            //
1423            TempDriverImagePath = DriverImageInfo->DriverImagePath;
1424            Status = gBS->LoadImage (
1425                            FALSE,
1426                            CallerImageHandle,
1427                            TempDriverImagePath,
1428                            NULL,
1429                            0,
1430                            &ImageHandle
1431                            );
1432            if (!EFI_ERROR (Status)) {
1433              //
1434              // Try to start the driver
1435              //
1436              Status = gBS->StartImage (ImageHandle, NULL, NULL);
1437              if (EFI_ERROR (Status)){
1438                DriverImageInfo->UnStartable = TRUE;
1439                DriverImageInfo->ImageHandle = NULL;
1440              } else {
1441                //
1442                // Find its related driver binding protocol
1443                // Driver binding handle may be different with its driver's Image handle
1444                //
1445                DriverBindingHandle = NULL;
1446                DriverBinding = GetBindingProtocolFromImageHandle (
1447                                   ImageHandle,
1448                                   &DriverBindingHandle
1449                                   );
1450                ASSERT (DriverBinding != NULL);
1451                DriverImageInfo->ImageHandle = ImageHandle;
1452              }
1453            } else {
1454              DriverImageInfo->UnLoadable = TRUE;
1455              DriverImageInfo->ImageHandle = NULL;
1456            }
1457          }
1458        }
1459        FreePool (ImageHandleBuffer);
1460      }
1461    }
1462    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1463  }
1464  //
1465  // Finish try to load and start the override driver of a controller, popup the controller's device path
1466  //
1467  PopDevPathStack (NULL);
1468
1469  //
1470  // return the DriverImageHandle for ControllerHandle
1471  //
1472  FoundLastReturned = FALSE;
1473  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1474  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1475    DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
1476    if (DriverImageInfo->ImageHandle != NULL) {
1477      if ((*DriverImageHandle == NULL) || FoundLastReturned) {
1478        //
1479        // If DriverImageHandle is NULL, then we just need to return the first driver.
1480        // If FoundLastReturned, this means we have just encountered the previously returned driver.
1481        // For both cases, we just return the image handle of this driver.
1482        //
1483        OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;
1484        *DriverImageHandle = DriverImageInfo->ImageHandle;
1485        return EFI_SUCCESS;
1486      } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){
1487        //
1488        // We have found the previously returned driver.
1489        //
1490        FoundLastReturned = TRUE;
1491      }
1492    }
1493    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1494  }
1495
1496  return EFI_NOT_FOUND;
1497}
1498
1499
1500/**
1501  Check mapping database whether already has the mapping info which
1502  records the input Controller to input DriverImage.
1503
1504  @param  ControllerDevicePath     The controller device path is to be check.
1505  @param  DriverImageDevicePath    The driver image device path is to be check.
1506  @param  MappingDataBase          Mapping database list entry pointer
1507  @param  DriverInfoNum            the controller's total override driver number
1508  @param  DriverImageNO            The driver order number for the input DriverImage.
1509                                   If the DriverImageDevicePath is NULL, DriverImageNO is not set.
1510
1511  @retval EFI_INVALID_PARAMETER    ControllerDevicePath or MappingDataBase is NULL.
1512  @retval EFI_NOT_FOUND            ControllerDevicePath is not found in MappingDataBase or
1513                                   DriverImageDevicePath is not found in the found DriverImage Info list.
1514  @retval EFI_SUCCESS              The controller's total override driver number and
1515                                   input DriverImage's order number is correctly return.
1516**/
1517EFI_STATUS
1518EFIAPI
1519CheckMapping (
1520  IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
1521  IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath  OPTIONAL,
1522  IN     LIST_ENTRY                                     *MappingDataBase,
1523  OUT    UINT32                                         *DriverInfoNum  OPTIONAL,
1524  OUT    UINT32                                         *DriverImageNO  OPTIONAL
1525  )
1526{
1527  LIST_ENTRY                  *OverrideItemListIndex;
1528  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
1529  LIST_ENTRY                  *ImageInfoListIndex;
1530  DRIVER_IMAGE_INFO           *DriverImageInfo;
1531  BOOLEAN                     Found;
1532  UINT32                      ImageNO;
1533  UINTN                       DevicePathSize;
1534
1535  if (ControllerDevicePath == NULL) {
1536    return EFI_INVALID_PARAMETER;
1537  }
1538  if (MappingDataBase == NULL) {
1539    return EFI_INVALID_PARAMETER;
1540  }
1541
1542  //
1543  // Search ControllerDevicePath in MappingDataBase
1544  //
1545  Found = FALSE;
1546  OverrideItem = NULL;
1547  OverrideItemListIndex = GetFirstNode (MappingDataBase);
1548  while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
1549    OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
1550    DevicePathSize = GetDevicePathSize (ControllerDevicePath);
1551    if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
1552      if (CompareMem (
1553            ControllerDevicePath,
1554            OverrideItem->ControllerDevicePath,
1555            DevicePathSize
1556            ) == 0
1557          ) {
1558        Found = TRUE;
1559        break;
1560      }
1561    }
1562    OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
1563  }
1564
1565  if (!Found) {
1566    //
1567    // ControllerDevicePath is not in MappingDataBase
1568    //
1569    return EFI_NOT_FOUND;
1570  }
1571
1572  ASSERT (OverrideItem->DriverInfoNum != 0);
1573  if (DriverInfoNum != NULL) {
1574    *DriverInfoNum = OverrideItem->DriverInfoNum;
1575  }
1576
1577  //
1578  // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath
1579  // in the controller's Driver Image Info List
1580  //
1581  if (DriverImageDevicePath == NULL) {
1582    return EFI_SUCCESS;
1583  }
1584  //
1585  // return the DriverImageHandle for ControllerHandle
1586  //
1587  ImageNO = 0;
1588  Found = FALSE;
1589  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1590  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1591    DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
1592    ImageNO++;
1593    DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
1594    if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
1595      if (CompareMem (
1596            DriverImageDevicePath,
1597            DriverImageInfo->DriverImagePath,
1598            GetDevicePathSize (DriverImageInfo->DriverImagePath)
1599            ) == 0
1600          ) {
1601        Found = TRUE;
1602        break;
1603      }
1604    }
1605    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1606  }
1607
1608  if (!Found) {
1609    //
1610    // DriverImageDevicePath is not found in the controller's Driver Image Info List
1611    //
1612    return EFI_NOT_FOUND;
1613  } else {
1614    if (DriverImageNO != NULL) {
1615      *DriverImageNO = ImageNO;
1616    }
1617    return EFI_SUCCESS;
1618  }
1619}
1620
1621
1622/**
1623  Insert a driver image as a controller's override driver into the mapping database.
1624  The driver image's order number is indicated by DriverImageNO.
1625
1626  @param  ControllerDevicePath     The controller device path need to add a
1627                                   override driver image item
1628  @param  DriverImageDevicePath    The driver image device path need to be insert
1629  @param  MappingDataBase          Mapping database list entry pointer
1630  @param  DriverImageNO            The inserted order number. If this number is taken,
1631                                   the larger available number will be used.
1632
1633  @retval EFI_INVALID_PARAMETER    ControllerDevicePath is NULL, or DriverImageDevicePath is NULL
1634                                   or MappingDataBase is NULL
1635  @retval EFI_ALREADY_STARTED      The input Controller to input DriverImage has been
1636                                   recorded into the mapping database.
1637  @retval EFI_SUCCESS              The Controller and DriverImage are inserted into
1638                                   the mapping database successfully.
1639
1640**/
1641EFI_STATUS
1642EFIAPI
1643InsertDriverImage (
1644  IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
1645  IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath,
1646  IN     LIST_ENTRY                                     *MappingDataBase,
1647  IN     UINT32                                         DriverImageNO
1648  )
1649{
1650  EFI_STATUS                  Status;
1651  LIST_ENTRY                  *OverrideItemListIndex;
1652  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
1653  LIST_ENTRY                  *ImageInfoListIndex;
1654  DRIVER_IMAGE_INFO           *DriverImageInfo;
1655  BOOLEAN                     Found;
1656  UINT32                      ImageNO;
1657  UINTN                       DevicePathSize;
1658
1659  if (ControllerDevicePath == NULL) {
1660    return EFI_INVALID_PARAMETER;
1661  }
1662  if (DriverImageDevicePath == NULL) {
1663    return EFI_INVALID_PARAMETER;
1664  }
1665  if (MappingDataBase == NULL) {
1666    return EFI_INVALID_PARAMETER;
1667  }
1668
1669  //
1670  // If the driver is already in the controller's Driver Image Info List,
1671  // just return EFI_ALREADY_STARTED.
1672  //
1673  Status = CheckMapping (
1674             ControllerDevicePath,
1675             DriverImageDevicePath,
1676             MappingDataBase,
1677             NULL,
1678             NULL
1679             );
1680  if (Status == EFI_SUCCESS) {
1681    return EFI_ALREADY_STARTED;
1682  }
1683
1684  //
1685  // Search the input ControllerDevicePath in MappingDataBase
1686  //
1687  Found = FALSE;
1688  OverrideItem = NULL;
1689  OverrideItemListIndex = GetFirstNode (MappingDataBase);
1690  while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
1691    OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
1692    DevicePathSize = GetDevicePathSize (ControllerDevicePath);
1693    if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
1694      if (CompareMem (
1695            ControllerDevicePath,
1696            OverrideItem->ControllerDevicePath,
1697            DevicePathSize
1698            ) == 0
1699          ) {
1700        Found = TRUE;
1701        break;
1702      }
1703    }
1704    OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
1705  }
1706  //
1707  // If cannot find, this is a new controller item
1708  // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base
1709  //
1710  if (!Found) {
1711    OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));
1712    ASSERT (OverrideItem != NULL);
1713    OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;
1714    OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);
1715    InitializeListHead (&OverrideItem->DriverInfoList);
1716    InsertTailList (MappingDataBase, &OverrideItem->Link);
1717  }
1718
1719  //
1720  // Prepare the driver image related DRIVER_IMAGE_INFO structure.
1721  //
1722  DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));
1723  ASSERT (DriverImageInfo != NULL);
1724  DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;
1725  DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath);
1726  //
1727  // Find the driver image wanted order location
1728  //
1729  ImageNO = 0;
1730  Found = FALSE;
1731  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1732  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1733    if (ImageNO == (DriverImageNO - 1)) {
1734      //
1735      // find the wanted order location, insert it
1736      //
1737      InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);
1738      OverrideItem->DriverInfoNum ++;
1739      Found = TRUE;
1740      break;
1741    }
1742    ImageNO++;
1743    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1744  }
1745
1746  if (!Found) {
1747    //
1748    // if not find the wanted order location, add it as last item of the controller mapping item
1749    //
1750    InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);
1751    OverrideItem->DriverInfoNum ++;
1752  }
1753
1754  return EFI_SUCCESS;
1755}
1756
1757
1758/**
1759  Delete a controller's override driver from the mapping database.
1760
1761  @param  ControllerDevicePath     The controller device path will be deleted
1762                                   when all drivers images on it are removed.
1763  @param  DriverImageDevicePath    The driver image device path will be delete.
1764                                   If NULL, all driver image will be delete.
1765  @param  MappingDataBase          Mapping database list entry pointer
1766
1767  @retval EFI_INVALID_PARAMETER    ControllerDevicePath is NULL, or MappingDataBase is NULL
1768  @retval EFI_NOT_FOUND            ControllerDevicePath is not found in MappingDataBase or
1769                                   DriverImageDevicePath is not found in the found DriverImage Info list.
1770  @retval EFI_SUCCESS              Delete the specified driver successfully.
1771
1772**/
1773EFI_STATUS
1774EFIAPI
1775DeleteDriverImage (
1776  IN     EFI_DEVICE_PATH_PROTOCOL                       *ControllerDevicePath,
1777  IN     EFI_DEVICE_PATH_PROTOCOL                       *DriverImageDevicePath,
1778  IN     LIST_ENTRY                                     *MappingDataBase
1779  )
1780{
1781  EFI_STATUS                  Status;
1782  LIST_ENTRY                  *OverrideItemListIndex;
1783  PLATFORM_OVERRIDE_ITEM      *OverrideItem;
1784  LIST_ENTRY                  *ImageInfoListIndex;
1785  DRIVER_IMAGE_INFO           *DriverImageInfo;
1786  BOOLEAN                     Found;
1787  UINTN                       DevicePathSize;
1788
1789  if (ControllerDevicePath == NULL) {
1790    return EFI_INVALID_PARAMETER;
1791  }
1792
1793  if (MappingDataBase == NULL) {
1794    return EFI_INVALID_PARAMETER;
1795  }
1796
1797  //
1798  // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.
1799  //
1800  Status = CheckMapping (
1801             ControllerDevicePath,
1802             DriverImageDevicePath,
1803             MappingDataBase,
1804             NULL,
1805             NULL
1806             );
1807  if (EFI_ERROR (Status)) {
1808    return EFI_NOT_FOUND;
1809  }
1810
1811  //
1812  // Search ControllerDevicePath in MappingDataBase
1813  //
1814  Found = FALSE;
1815  OverrideItem = NULL;
1816  OverrideItemListIndex = GetFirstNode (MappingDataBase);
1817  while (!IsNull (MappingDataBase, OverrideItemListIndex)) {
1818    OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);
1819    DevicePathSize = GetDevicePathSize (ControllerDevicePath);
1820    if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {
1821      if (CompareMem (
1822            ControllerDevicePath,
1823            OverrideItem->ControllerDevicePath,
1824            DevicePathSize
1825            ) == 0
1826          ) {
1827        Found = TRUE;
1828        break;
1829      }
1830    }
1831    OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);
1832  }
1833
1834  ASSERT (Found);
1835  ASSERT (OverrideItem->DriverInfoNum != 0);
1836
1837  Found = FALSE;
1838  ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);
1839  while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {
1840    DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);
1841    ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);
1842    if (DriverImageDevicePath != NULL) {
1843      //
1844      // Search for the specified DriverImageDevicePath and remove it, then break.
1845      //
1846      DevicePathSize = GetDevicePathSize (DriverImageDevicePath);
1847      if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {
1848        if (CompareMem (
1849              DriverImageDevicePath,
1850              DriverImageInfo->DriverImagePath,
1851              GetDevicePathSize (DriverImageInfo->DriverImagePath)
1852              ) == 0
1853            ) {
1854          Found = TRUE;
1855          FreePool(DriverImageInfo->DriverImagePath);
1856          RemoveEntryList (&DriverImageInfo->Link);
1857          OverrideItem->DriverInfoNum --;
1858          break;
1859        }
1860      }
1861    } else {
1862      //
1863      // Remove all existing driver image info entries, so no break here.
1864      //
1865      Found = TRUE;
1866      FreePool(DriverImageInfo->DriverImagePath);
1867      RemoveEntryList (&DriverImageInfo->Link);
1868      OverrideItem->DriverInfoNum --;
1869    }
1870  }
1871
1872  //
1873  // Confirm all driver image info entries have been removed,
1874  // if DriverImageDevicePath is NULL.
1875  //
1876  if (DriverImageDevicePath == NULL) {
1877    ASSERT (OverrideItem->DriverInfoNum == 0);
1878  }
1879  //
1880  // If Override Item has no driver image info entry, then delete this item.
1881  //
1882  if (OverrideItem->DriverInfoNum == 0) {
1883    FreePool(OverrideItem->ControllerDevicePath);
1884    RemoveEntryList (&OverrideItem->Link);
1885    FreePool (OverrideItem);
1886  }
1887
1888  if (!Found) {
1889    //
1890    // DriverImageDevicePath is not NULL and cannot be found in the controller's
1891    // driver image info list.
1892    //
1893    return EFI_NOT_FOUND;
1894  }
1895
1896  return EFI_SUCCESS;
1897}
1898