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