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