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