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