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