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