]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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
fe1e36e5 23LIST_ENTRY mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack);\r
b290614d 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
b290614d 669 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
3012ce5c 670 EFI_HANDLE DriverBindingHandle;\r
b290614d 671 BOOLEAN FoundLastReturned;\r
672 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
673 DRIVER_IMAGE_INFO *DriverImageInfo;\r
674 LIST_ENTRY *OverrideItemListIndex;\r
675 LIST_ENTRY *ImageInfoListIndex;\r
676 EFI_DEVICE_PATH_PROTOCOL *TempDriverImagePath;\r
677 EFI_HANDLE ImageHandle;\r
678 EFI_HANDLE Handle;\r
23d64dda 679 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
b290614d 680 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
681 UINTN DevicePathSize;\r
682\r
683 //\r
684 // Check that ControllerHandle is a valid handle\r
685 //\r
686 if (ControllerHandle == NULL) {\r
687 return EFI_INVALID_PARAMETER;\r
688 }\r
689\r
690 Status = gBS->HandleProtocol (\r
691 ControllerHandle,\r
692 &gEfiDevicePathProtocolGuid,\r
693 (VOID **) &ControllerDevicePath\r
694 );\r
695 if (EFI_ERROR (Status) || ControllerDevicePath == NULL) {\r
696 return EFI_INVALID_PARAMETER;\r
697 }\r
698\r
699 //\r
700 // Search ControllerDevicePath in MappingDataBase\r
701 //\r
702 OverrideItem = NULL;\r
703 ControllerFound = FALSE;\r
704 OverrideItemListIndex = MappingDataBase->ForwardLink;\r
705 while (OverrideItemListIndex != MappingDataBase){\r
706 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
707 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
708 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
709 if (CompareMem (\r
710 ControllerDevicePath,\r
711 OverrideItem->ControllerDevicePath,\r
712 GetDevicePathSize (OverrideItem->ControllerDevicePath)\r
713 ) == 0\r
714 ) {\r
715 ControllerFound = TRUE;\r
716 break;\r
717 }\r
718\r
719 }\r
720 OverrideItemListIndex = OverrideItemListIndex->ForwardLink;\r
721 }\r
722\r
723 if (!ControllerFound) {\r
724 return EFI_NOT_FOUND;\r
725 }\r
726 //\r
727 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.\r
728 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().\r
729 //\r
730 if (*DriverImageHandle != NULL) {\r
731 if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) {\r
732 return EFI_INVALID_PARAMETER;\r
733 }\r
734 }\r
735 //\r
736 // The GetDriverPath() maybe called recursively, because it use ConnectDevicePath() internally,\r
737 // so should check whether there is a dead loop.\r
738 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,\r
739 // and check the controller device path whether appear again during the GetDriverPath() call.\r
740 //\r
741 if (CheckExistInStack(OverrideItem->ControllerDevicePath)) {\r
742 //\r
743 // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice\r
744 //\r
745 return EFI_UNSUPPORTED;\r
746 }\r
747 PushDevPathStack (OverrideItem->ControllerDevicePath);\r
748\r
749 //\r
750 // Check every override driver, try to load and start them\r
751 //\r
752 ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;\r
753 while (ImageInfoListIndex != &OverrideItem->DriverInfoList){\r
754 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
755 if (DriverImageInfo->ImageHandle == NULL) {\r
756 //\r
757 // Skip if the image is unloadable or unstartable\r
758 //\r
759 if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) {\r
760 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
761 //\r
762 // 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
763 // 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
764 //\r
765 Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle);\r
766 if (!EFI_ERROR (Status)) {\r
767 FreePool(DriverImageInfo->DriverImagePath);\r
768 DriverImageInfo->DriverImagePath = TempDriverImagePath;\r
769 }\r
770 //\r
771 // Get all Loaded Image protocol to check whether the driver image has been loaded and started\r
772 //\r
773 ImageFound = FALSE;\r
774 ImageHandleCount = 0;\r
775 Status = gBS->LocateHandleBuffer (\r
776 ByProtocol,\r
777 &gEfiLoadedImageProtocolGuid,\r
778 NULL,\r
779 &ImageHandleCount,\r
780 &ImageHandleBuffer\r
781 );\r
782 if (EFI_ERROR (Status) || (ImageHandleCount == 0)) {\r
783 return EFI_NOT_FOUND;\r
784 }\r
785\r
786 for(Index = 0; Index < ImageHandleCount; Index ++) {\r
b290614d 787 //\r
23d64dda 788 // Get the EFI Loaded Image Device Path Protocol\r
b290614d 789 //\r
23d64dda 790 LoadedImageDevicePath = NULL;\r
b290614d 791 Status = gBS->HandleProtocol (\r
23d64dda 792 ImageHandleBuffer[Index],\r
793 &gEfiLoadedImageDevicePathProtocolGuid,\r
794 (VOID **) &LoadedImageDevicePath\r
b290614d 795 );\r
796 if (EFI_ERROR (Status)) {\r
797 //\r
23d64dda 798 // Maybe Not all EFI Loaded Image Device Path Protocol existed.\r
b290614d 799 //\r
800 continue;\r
801 }\r
802\r
b290614d 803 DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);\r
23d64dda 804 if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) {\r
b290614d 805 if (CompareMem (\r
806 DriverImageInfo->DriverImagePath,\r
23d64dda 807 LoadedImageDevicePath,\r
808 GetDevicePathSize (LoadedImageDevicePath)\r
b290614d 809 ) == 0\r
810 ) {\r
811 ImageFound = TRUE;\r
812 break;\r
813 }\r
814 }\r
815 }\r
816\r
817 if (ImageFound) {\r
3012ce5c 818 //\r
819 // Find its related driver binding protocol\r
820 // Driver binding handle may be different with its driver's Image handle,\r
821 //\r
822 DriverBindingHandle = NULL;\r
823 DriverBinding = GetBindingProtocolFromImageHandle (\r
824 ImageHandleBuffer[Index],\r
825 &DriverBindingHandle\r
826 );\r
827 ASSERT (DriverBinding != NULL);\r
b290614d 828 DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];\r
3012ce5c 829 } else if (GetCurrentTpl() <= TPL_CALLBACK){\r
b290614d 830 //\r
831 // The driver image has not been loaded and started, need try to load and start it now\r
832 // Try to connect all device in the driver image path\r
833 //\r
3012ce5c 834 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but\r
835 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )\r
836 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit\r
837 // to use LoadImage() and StartImage() in CALLBACK TPL.\r
838 //\r
b290614d 839 Status = ConnectDevicePath (DriverImageInfo->DriverImagePath);\r
840 //\r
841 // 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
842 //\r
843 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
844 gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);\r
845 //\r
846 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle\r
847 //\r
848 Status = gBS->HandleProtocol(\r
849 Handle,\r
850 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
851 (VOID **) &BusSpecificDriverOverride\r
852 );\r
853 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {\r
854 ImageHandle = NULL;\r
855 Status = BusSpecificDriverOverride->GetDriver (\r
856 BusSpecificDriverOverride,\r
857 &ImageHandle\r
858 );\r
859 if (!EFI_ERROR (Status)) {\r
3012ce5c 860 //\r
861 // Find its related driver binding protocol\r
862 // Driver binding handle may be different with its driver's Image handle\r
863 //\r
864 DriverBindingHandle = NULL;\r
865 DriverBinding = GetBindingProtocolFromImageHandle (\r
866 ImageHandle,\r
867 &DriverBindingHandle\r
868 );\r
869 ASSERT (DriverBinding != NULL);\r
b290614d 870 DriverImageInfo->ImageHandle = ImageHandle;\r
871 }\r
872 }\r
873 //\r
874 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.\r
875 // Only file path media or FwVol Device Path Node remain if all device is connected\r
876 //\r
877 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
878 gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);\r
879 if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) &&\r
880 (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) ||\r
881 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL)\r
882 ) {\r
883 //\r
884 // Try to load the driver\r
885 //\r
886 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
887 Status = gBS->LoadImage (\r
888 FALSE,\r
889 CallerImageHandle,\r
890 TempDriverImagePath,\r
891 NULL,\r
892 0,\r
893 &ImageHandle\r
894 );\r
895 if (!EFI_ERROR (Status)) {\r
896 //\r
897 // Try to start the driver\r
898 //\r
899 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
900 if (EFI_ERROR (Status)){\r
901 DriverImageInfo->UnStartable = TRUE;\r
902 DriverImageInfo->ImageHandle = NULL;\r
903 } else {\r
3012ce5c 904 //\r
905 // Find its related driver binding protocol\r
906 // Driver binding handle may be different with its driver's Image handle\r
907 //\r
908 DriverBindingHandle = NULL;\r
909 DriverBinding = GetBindingProtocolFromImageHandle (\r
910 ImageHandle,\r
911 &DriverBindingHandle\r
912 );\r
913 ASSERT (DriverBinding != NULL);\r
b290614d 914 DriverImageInfo->ImageHandle = ImageHandle;\r
915 }\r
916 } else {\r
917 DriverImageInfo->UnLoadable = TRUE;\r
918 DriverImageInfo->ImageHandle = NULL;\r
919 }\r
920 }\r
921 }\r
922 FreePool (ImageHandleBuffer);\r
923 }\r
924 }\r
925 ImageInfoListIndex = ImageInfoListIndex->ForwardLink;\r
926 }\r
927 //\r
928 // Finish try to load and start the override driver of a controller, popup the controller's device path\r
929 //\r
930 PopDevPathStack (NULL);\r
931\r
932 //\r
933 // return the DriverImageHandle for ControllerHandle\r
934 //\r
935 FoundLastReturned = FALSE;\r
936 ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;\r
937 while (ImageInfoListIndex != &OverrideItem->DriverInfoList){\r
938 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
939 if (DriverImageInfo->ImageHandle != NULL) {\r
940 if ((*DriverImageHandle == NULL) || FoundLastReturned) {\r
941 OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;\r
942 *DriverImageHandle = DriverImageInfo->ImageHandle;\r
943 return EFI_SUCCESS;\r
944 } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){\r
945 FoundLastReturned = TRUE;\r
946 }\r
947 }\r
948 ImageInfoListIndex = ImageInfoListIndex->ForwardLink;\r
949 }\r
950\r
951 return EFI_NOT_FOUND;\r
952}\r
953\r
954\r
955/**\r
956 Check mapping database whether already has the mapping info which\r
957 records the input Controller to input DriverImage.\r
958 If has, the controller's total override driver number and input DriverImage's order number is return.\r
959\r
960 @param ControllerDevicePath The controller device path need to add a\r
961 override driver image item\r
962 @param DriverImageDevicePath The driver image device path need to be insert\r
963 @param MappingDataBase Mapping database list entry pointer\r
964 @param DriverInfoNum the controller's total override driver number\r
965 @param DriverImageNO The inserted order number\r
966\r
967 @return EFI_INVALID_PARAMETER\r
968 @return EFI_NOT_FOUND\r
969 @return EFI_SUCCESS\r
970\r
971**/\r
972EFI_STATUS\r
973EFIAPI\r
974CheckMapping (\r
975 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
976 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,\r
977 IN LIST_ENTRY * MappingDataBase,\r
978 OUT UINT32 *DriverInfoNum,\r
979 OUT UINT32 *DriverImageNO\r
980 )\r
981{\r
982 LIST_ENTRY *OverrideItemListIndex;\r
983 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
984 LIST_ENTRY *ImageInfoListIndex;\r
985 DRIVER_IMAGE_INFO *DriverImageInfo;\r
986 BOOLEAN Found;\r
987 UINT32 ImageNO;\r
988 UINTN DevicePathSize;\r
989\r
990 //\r
991 // Check that ControllerHandle is a valid handle\r
992 //\r
993 if (ControllerDevicePath == NULL) {\r
994 return EFI_INVALID_PARAMETER;\r
995 }\r
996 if (MappingDataBase == NULL) {\r
997 return EFI_INVALID_PARAMETER;\r
998 }\r
999 //\r
1000 // Search ControllerDevicePath in MappingDataBase\r
1001 //\r
1002 Found = FALSE;\r
1003 OverrideItem = NULL;\r
1004 OverrideItemListIndex = MappingDataBase->ForwardLink;\r
1005 while (OverrideItemListIndex != MappingDataBase){\r
1006 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1007 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1008 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1009 if (CompareMem (\r
1010 ControllerDevicePath,\r
1011 OverrideItem->ControllerDevicePath,\r
1012 GetDevicePathSize (OverrideItem->ControllerDevicePath)\r
1013 ) == 0\r
1014 ) {\r
1015 Found = TRUE;\r
1016 break;\r
1017 }\r
1018 }\r
1019 OverrideItemListIndex = OverrideItemListIndex->ForwardLink;\r
1020 }\r
1021\r
1022 if (!Found) {\r
1023 return EFI_NOT_FOUND;\r
1024 }\r
1025\r
1026 ASSERT (OverrideItem->DriverInfoNum != 0);\r
1027 if (DriverInfoNum != NULL) {\r
1028 *DriverInfoNum = OverrideItem->DriverInfoNum;\r
1029 }\r
1030\r
1031\r
1032 if (DriverImageDevicePath == NULL) {\r
1033 return EFI_SUCCESS;\r
1034 }\r
1035 //\r
1036 // return the DriverImageHandle for ControllerHandle\r
1037 //\r
1038 ImageNO = 0;\r
1039 Found = FALSE;\r
1040 ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;\r
1041 while (ImageInfoListIndex != &OverrideItem->DriverInfoList){\r
1042 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1043 ImageNO++;\r
1044 DevicePathSize = GetDevicePathSize (DriverImageDevicePath);\r
1045 if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {\r
1046 if (CompareMem (\r
1047 DriverImageDevicePath,\r
1048 DriverImageInfo->DriverImagePath,\r
1049 GetDevicePathSize (DriverImageInfo->DriverImagePath)\r
1050 ) == 0\r
1051 ) {\r
1052 Found = TRUE;\r
1053 break;\r
1054 }\r
1055 }\r
1056 ImageInfoListIndex = ImageInfoListIndex->ForwardLink;\r
1057 }\r
1058\r
1059 if (!Found) {\r
1060 return EFI_NOT_FOUND;\r
1061 } else {\r
1062 if (DriverImageNO != NULL) {\r
1063 *DriverImageNO = ImageNO;\r
1064 }\r
1065 return EFI_SUCCESS;\r
1066 }\r
1067\r
1068}\r
1069\r
1070\r
1071/**\r
1072 Insert a driver image as a controller's override driver into the mapping database.\r
1073 The driver image's order number is indicated by DriverImageNO.\r
1074\r
1075 @param ControllerDevicePath The controller device path need to add a\r
1076 override driver image item\r
1077 @param DriverImageDevicePath The driver image device path need to be insert\r
1078 @param MappingDataBase Mapping database list entry pointer\r
1079 @param DriverImageNO The inserted order number\r
1080\r
1081 @return EFI_INVALID_PARAMETER\r
1082 @return EFI_ALREADY_STARTED\r
1083 @return EFI_SUCCESS\r
1084\r
1085**/\r
1086EFI_STATUS\r
1087EFIAPI\r
1088InsertDriverImage (\r
1089 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
1090 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,\r
1091 IN LIST_ENTRY *MappingDataBase,\r
1092 IN UINT32 DriverImageNO\r
1093 )\r
1094{\r
1095 EFI_STATUS Status;\r
1096 LIST_ENTRY *OverrideItemListIndex;\r
1097 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
1098 LIST_ENTRY *ImageInfoListIndex;\r
1099 DRIVER_IMAGE_INFO *DriverImageInfo;\r
1100 BOOLEAN Found;\r
1101 UINT32 ImageNO;\r
1102 UINTN DevicePathSize;\r
1103\r
1104 //\r
1105 // Check that ControllerHandle is a valid handle\r
1106 //\r
1107 if (ControllerDevicePath == NULL) {\r
1108 return EFI_INVALID_PARAMETER;\r
1109 }\r
1110 if (DriverImageDevicePath == NULL) {\r
1111 return EFI_INVALID_PARAMETER;\r
1112 }\r
1113 if (MappingDataBase == NULL) {\r
1114 return EFI_INVALID_PARAMETER;\r
1115 }\r
1116\r
1117 Status = CheckMapping (\r
1118 ControllerDevicePath,\r
1119 DriverImageDevicePath,\r
1120 MappingDataBase,\r
1121 NULL,\r
1122 NULL\r
1123 );\r
1124 if (Status == EFI_SUCCESS) {\r
1125 return EFI_ALREADY_STARTED;\r
1126 }\r
1127\r
1128 //\r
1129 // Search the input ControllerDevicePath in MappingDataBase\r
1130 //\r
1131 Found = FALSE;\r
1132 OverrideItem = NULL;\r
1133 OverrideItemListIndex = MappingDataBase->ForwardLink;\r
1134 while (OverrideItemListIndex != MappingDataBase){\r
1135 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1136 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1137 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1138 if (CompareMem (\r
1139 ControllerDevicePath,\r
1140 OverrideItem->ControllerDevicePath,\r
1141 GetDevicePathSize (OverrideItem->ControllerDevicePath)\r
1142 ) == 0\r
1143 ) {\r
1144 Found = TRUE;\r
1145 break;\r
1146 }\r
1147 }\r
1148 OverrideItemListIndex = OverrideItemListIndex->ForwardLink;\r
1149 }\r
1150 //\r
1151 // If cannot find, this is a new controller item\r
1152 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base\r
1153 //\r
1154 if (!Found) {\r
1155 OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));\r
1156 ASSERT (OverrideItem != NULL);\r
1157 OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;\r
1158 OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);\r
1159 InitializeListHead (&OverrideItem->DriverInfoList);\r
1160 InsertTailList (MappingDataBase, &OverrideItem->Link);\r
1161 }\r
1162\r
1163 //\r
1164 // Prepare the driver image related DRIVER_IMAGE_INFO structure.\r
1165 //\r
1166 DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));\r
1167 ASSERT (DriverImageInfo != NULL);\r
1168 DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;\r
1169 DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath);\r
1170 //\r
1171 // Find the driver image wantted order location\r
1172 //\r
1173 ImageNO = 0;\r
1174 Found = FALSE;\r
1175 ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;\r
1176 while (ImageInfoListIndex != &OverrideItem->DriverInfoList){\r
1177 if (ImageNO == (DriverImageNO - 1)) {\r
1178 //\r
1179 // find the wantted order location, insert it\r
1180 //\r
1181 InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);\r
1182 OverrideItem->DriverInfoNum ++;\r
1183 Found = TRUE;\r
1184 break;\r
1185 }\r
1186 //DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1187 ImageNO++;\r
1188 ImageInfoListIndex = ImageInfoListIndex->ForwardLink;\r
1189 }\r
1190\r
1191 if (!Found) {\r
1192 //\r
1193 // if not find the wantted order location, add it as last item of the controller mapping item\r
1194 //\r
1195 InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);\r
1196 OverrideItem->DriverInfoNum ++;\r
1197 }\r
1198\r
1199 return EFI_SUCCESS;\r
1200}\r
1201\r
1202\r
1203/**\r
1204 Delete a controller's override driver from the mapping database.\r
1205\r
1206 @param ControllerDevicePath The controller device path need to add a\r
1207 override driver image item\r
1208 @param DriverImageDevicePath The driver image device path need to be insert\r
1209 @param MappingDataBase Mapping database list entry pointer\r
1210 @param DriverImageNO The inserted order number\r
1211\r
1212 @return EFI_INVALID_PARAMETER\r
1213 @return EFI_NOT_FOUND\r
1214 @return EFI_SUCCESS\r
1215\r
1216**/\r
1217EFI_STATUS\r
1218EFIAPI\r
1219DeleteDriverImage (\r
1220 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
1221 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,\r
1222 IN LIST_ENTRY *MappingDataBase\r
1223 )\r
1224{\r
1225 EFI_STATUS Status;\r
1226 LIST_ENTRY *OverrideItemListIndex;\r
1227 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
1228 LIST_ENTRY *ImageInfoListIndex;\r
1229 DRIVER_IMAGE_INFO *DriverImageInfo;\r
1230 BOOLEAN Found;\r
1231 UINTN DevicePathSize;\r
1232\r
1233 //\r
1234 // Check that ControllerHandle is a valid handle\r
1235 //\r
1236 if (ControllerDevicePath == NULL) {\r
1237 return EFI_INVALID_PARAMETER;\r
1238 }\r
1239\r
1240 if (MappingDataBase == NULL) {\r
1241 return EFI_INVALID_PARAMETER;\r
1242 }\r
1243\r
1244 Status = CheckMapping (\r
1245 ControllerDevicePath,\r
1246 DriverImageDevicePath,\r
1247 MappingDataBase,\r
1248 NULL,\r
1249 NULL\r
1250 );\r
1251 if (Status == EFI_NOT_FOUND) {\r
1252 return EFI_NOT_FOUND;\r
1253 }\r
1254\r
1255 //\r
1256 // Search ControllerDevicePath in MappingDataBase\r
1257 //\r
1258 Found = FALSE;\r
1259 OverrideItem = NULL;\r
1260 OverrideItemListIndex = MappingDataBase->ForwardLink;\r
1261 while (OverrideItemListIndex != MappingDataBase){\r
1262 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1263 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1264 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1265 if (CompareMem (\r
1266 ControllerDevicePath,\r
1267 OverrideItem->ControllerDevicePath,\r
1268 GetDevicePathSize (OverrideItem->ControllerDevicePath)\r
1269 ) == 0\r
1270 ) {\r
1271 Found = TRUE;\r
1272 break;\r
1273 }\r
1274 }\r
1275 OverrideItemListIndex = OverrideItemListIndex->ForwardLink;\r
1276 }\r
1277\r
1278 ASSERT (Found);\r
1279 ASSERT (OverrideItem->DriverInfoNum != 0);\r
1280 //\r
1281 //\r
1282 //\r
1283 Found = FALSE;\r
1284 ImageInfoListIndex = OverrideItem->DriverInfoList.ForwardLink;\r
1285 while (ImageInfoListIndex != &OverrideItem->DriverInfoList){\r
1286 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1287 ImageInfoListIndex = ImageInfoListIndex->ForwardLink;\r
1288 if (DriverImageDevicePath != NULL) {\r
1289 DevicePathSize = GetDevicePathSize (DriverImageDevicePath);\r
1290 if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {\r
1291 if (CompareMem (\r
1292 DriverImageDevicePath,\r
1293 DriverImageInfo->DriverImagePath,\r
1294 GetDevicePathSize (DriverImageInfo->DriverImagePath)\r
1295 ) == 0\r
1296 ) {\r
1297 Found = TRUE;\r
1298 FreePool(DriverImageInfo->DriverImagePath);\r
1299 RemoveEntryList (&DriverImageInfo->Link);\r
1300 OverrideItem->DriverInfoNum --;\r
1301 break;\r
1302 }\r
1303 }\r
1304 } else {\r
1305 Found = TRUE;\r
1306 FreePool(DriverImageInfo->DriverImagePath);\r
1307 RemoveEntryList (&DriverImageInfo->Link);\r
1308 OverrideItem->DriverInfoNum --;\r
1309 }\r
1310 }\r
1311\r
1312 if (DriverImageDevicePath == NULL) {\r
1313 ASSERT (OverrideItem->DriverInfoNum == 0);\r
1314 }\r
1315\r
1316 if (OverrideItem->DriverInfoNum == 0) {\r
1317 FreePool(OverrideItem->ControllerDevicePath);\r
1318 RemoveEntryList (&OverrideItem->Link);\r
1319 FreePool (OverrideItem);\r
1320 }\r
1321\r
1322 if (!Found) {\r
1323 return EFI_NOT_FOUND;\r
1324 }\r
1325\r
1326 return EFI_SUCCESS;\r
1327}\r
1328\r
1329\r
1330/**\r
1331 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to\r
1332 a set of Driver Device Paths.\r
1333\r
1334 None\r
1335\r
1336 @return EFI_SUCCESS\r
1337\r
1338**/\r
1339EFI_STATUS\r
1340EFIAPI\r
1341DeleteOverridesVariables (\r
1342 VOID\r
1343 )\r
1344{\r
1345 EFI_STATUS Status;\r
1346 VOID *VariableBuffer;\r
1347 UINTN VariableNum;\r
1348 UINTN BufferSize;\r
1349 UINTN Index;\r
1350 CHAR16 OverrideVariableName[40];\r
1351\r
1352 //\r
1353 // Get environment variable(s) number\r
1354 //\r
1355 VariableNum =0;\r
1356 VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiOverrideVariableGuid, &BufferSize);\r
1357 VariableNum ++;\r
1358 if (VariableBuffer == NULL) {\r
1359 return EFI_NOT_FOUND;\r
1360 }\r
1361 //\r
1362 // Check NotEnd to get all PlatDriOverX variable(s)\r
1363 //\r
1364 while (*(UINT32*)VariableBuffer) {\r
1365 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);\r
1366 VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiOverrideVariableGuid, &BufferSize);\r
1367 VariableNum ++;\r
1368 ASSERT (VariableBuffer != NULL);\r
1369 }\r
1370\r
1371 Status = gRT->SetVariable (\r
1372 L"PlatDriOver",\r
1373 &gEfiOverrideVariableGuid,\r
1374 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1375 0,\r
1376 NULL\r
1377 );\r
1378 ASSERT (!EFI_ERROR (Status));\r
1379 for (Index = 1; Index < VariableNum; Index++) {\r
1380 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index);\r
1381 Status = gRT->SetVariable (\r
1382 OverrideVariableName,\r
1383 &gEfiOverrideVariableGuid,\r
1384 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1385 0,\r
1386 NULL\r
1387 );\r
1388 ASSERT (!EFI_ERROR (Status));\r
1389 }\r
1390 return EFI_SUCCESS;\r
1391}\r
1392\r
1393\r
1394/**\r
1395 Push a controller device path into a globle device path list\r
1396\r
1397 @param ControllerDevicePath The controller device path need to push into\r
1398 stack\r
1399\r
1400 @return EFI_SUCCESS\r
1401\r
1402**/\r
1403EFI_STATUS\r
1404EFIAPI\r
1405PushDevPathStack (\r
1406 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1407 )\r
1408{\r
1409 DEVICE_PATH_STACK_ITEM *DevicePathStackItem;\r
1410\r
1411 DevicePathStackItem = AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM));\r
1412 ASSERT (DevicePathStackItem != NULL);\r
1413 DevicePathStackItem->Signature = DEVICE_PATH_STACK_ITEM_SIGNATURE;\r
1414 DevicePathStackItem->DevicePath = DuplicateDevicePath (DevicePath);\r
1415 InsertTailList (&mDevicePathStack, &DevicePathStackItem->Link);\r
1416 return EFI_SUCCESS;\r
1417}\r
1418\r
1419\r
1420/**\r
1421 Pop a controller device path from a globle device path list\r
1422\r
1423 @param ControllerDevicePath The controller device path retrieved from stack\r
1424\r
1425 @return EFI_SUCCESS\r
1426 @return EFI_NOT_FOUND\r
1427\r
1428**/\r
1429EFI_STATUS\r
1430EFIAPI\r
1431PopDevPathStack (\r
1432 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath\r
1433 )\r
1434{\r
1435 DEVICE_PATH_STACK_ITEM *DevicePathStackItem;\r
1436 LIST_ENTRY *ItemListIndex;\r
1437\r
1438 ItemListIndex = mDevicePathStack.BackLink;\r
1439 if (ItemListIndex != &mDevicePathStack){\r
1440 DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);\r
1441 if (DevicePath != NULL) {\r
1442 *DevicePath = DuplicateDevicePath (DevicePathStackItem->DevicePath);\r
1443 }\r
1444 FreePool (DevicePathStackItem->DevicePath);\r
1445 RemoveEntryList (&DevicePathStackItem->Link);\r
1446 FreePool (DevicePathStackItem);\r
1447 return EFI_SUCCESS;\r
1448 }\r
1449 return EFI_NOT_FOUND;\r
1450}\r
1451\r
1452\r
1453/**\r
1454 Check whether a controller device path is in a globle device path list\r
1455\r
1456 @param ControllerDevicePath The controller device path need to check\r
1457\r
1458 @return True\r
1459 @return False\r
1460\r
1461**/\r
1462BOOLEAN\r
1463EFIAPI\r
1464CheckExistInStack (\r
1465 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
1466 )\r
1467{\r
1468 DEVICE_PATH_STACK_ITEM *DevicePathStackItem;\r
1469 LIST_ENTRY *ItemListIndex;\r
1470 BOOLEAN Found;\r
1471 UINTN DevicePathSize;\r
1472\r
1473 Found = FALSE;\r
1474 ItemListIndex = mDevicePathStack.BackLink;\r
1475 while (ItemListIndex != &mDevicePathStack){\r
1476 DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE);\r
1477 DevicePathSize = GetDevicePathSize (DevicePath);\r
1478 if (DevicePathSize == GetDevicePathSize (DevicePathStackItem->DevicePath)) {\r
1479 if (CompareMem (\r
1480 DevicePath,\r
1481 DevicePathStackItem->DevicePath,\r
1482 GetDevicePathSize (DevicePathStackItem->DevicePath)\r
1483 ) == 0\r
1484 ) {\r
1485 Found = TRUE;\r
1486 break;\r
1487 }\r
1488 }\r
1489 ItemListIndex = ItemListIndex->BackLink;\r
1490 }\r
1491\r
1492 return Found;\r
1493}\r
1494\r
1495\r
1496/**\r
1497 According to a file guild, check a Fv file device path is valid. If it is invalid,\r
1498 try to return the valid device path.\r
1499 FV address maybe changes for memory layout adjust from time to time, use this funciton\r
1500 could promise the Fv file device path is right.\r
1501\r
1502 @param DevicePath on input, the Fv file device path need to check\r
1503 on output, the updated valid Fv file device path\r
1504 @param FileGuid the Fv file guild\r
1505 @param CallerImageHandle\r
1506\r
1507 @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid\r
1508 parameter\r
1509 @retval EFI_UNSUPPORTED the input DevicePath does not contain Fv file\r
1510 guild at all\r
1511 @retval EFI_ALREADY_STARTED the input DevicePath has pointed to Fv file, it\r
1512 is valid\r
1513 @retval EFI_SUCCESS has successfully updated the invalid DevicePath,\r
1514 and return the updated device path in DevicePath\r
1515\r
1516**/\r
1517EFI_STATUS\r
1518EFIAPI\r
1519UpdateFvFileDevicePath (\r
1520 IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath,\r
1521 IN EFI_GUID *FileGuid,\r
1522 IN EFI_HANDLE CallerImageHandle\r
1523 )\r
1524{\r
1525 EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;\r
1526 EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode;\r
1527 EFI_STATUS Status;\r
1528 EFI_GUID *GuidPoint;\r
1529 UINTN Index;\r
1530 UINTN FvHandleCount;\r
1531 EFI_HANDLE *FvHandleBuffer;\r
1532 EFI_FV_FILETYPE Type;\r
1533 UINTN Size;\r
1534 EFI_FV_FILE_ATTRIBUTES Attributes;\r
1535 UINT32 AuthenticationStatus;\r
1536 BOOLEAN FindFvFile;\r
1537 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
1538 EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;\r
1539 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode;\r
1540 EFI_HANDLE FoundFvHandle;\r
1541 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
1542 BOOLEAN HasFVNode;\r
1543\r
1544 if ((DevicePath == NULL) || (*DevicePath == NULL)) {\r
1545 return EFI_INVALID_PARAMETER;\r
1546 }\r
1547\r
1548 //\r
1549 // Check whether the device path point to the default the input Fv file\r
1550 //\r
1551 TempDevicePath = *DevicePath;\r
1552 LastDeviceNode = TempDevicePath;\r
1553 while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
1554 LastDeviceNode = TempDevicePath;\r
1555 TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
1556 }\r
1557 GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode (\r
1558 (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode\r
1559 );\r
1560 if (GuidPoint == NULL) {\r
1561 //\r
1562 // if this option does not points to a Fv file, just return EFI_UNSUPPORTED\r
1563 //\r
1564 return EFI_UNSUPPORTED;\r
1565 }\r
1566\r
1567 if (FileGuid != NULL) {\r
1568 if (!CompareGuid (GuidPoint, FileGuid)) {\r
1569 //\r
1570 // If the Fv file is not the input file guid, just return EFI_UNSUPPORTED\r
1571 //\r
1572 return EFI_UNSUPPORTED;\r
1573 }\r
1574 } else {\r
1575 FileGuid = GuidPoint;\r
1576 }\r
1577\r
1578 //\r
1579 // Check to see if the device path contain memory map node\r
1580 //\r
1581 TempDevicePath = *DevicePath;\r
1582 HasFVNode = FALSE;\r
1583 while (!EfiIsDevicePathEnd (TempDevicePath)) {\r
1584 //\r
1585 // Use old Device Path\r
1586 //\r
1587 if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH &&\r
1588 DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) {\r
1589 HasFVNode = TRUE;\r
1590 break;\r
1591 }\r
1592 TempDevicePath = EfiNextDevicePathNode (TempDevicePath);\r
1593 }\r
1594\r
1595 if (!HasFVNode) {\r
1596 return EFI_UNSUPPORTED;\r
1597 }\r
1598\r
1599 //\r
1600 // Check whether the input Fv file device path is valid\r
1601 //\r
1602 TempDevicePath = *DevicePath;\r
1603 FoundFvHandle = NULL;\r
1604 Status = gBS->LocateDevicePath (\r
1605 &gEfiFirmwareVolume2ProtocolGuid,\r
1606 &TempDevicePath,\r
1607 &FoundFvHandle\r
1608 );\r
1609 if (!EFI_ERROR (Status)) {\r
1610 Status = gBS->HandleProtocol (\r
1611 FoundFvHandle,\r
1612 &gEfiFirmwareVolume2ProtocolGuid,\r
1613 (VOID **) &Fv\r
1614 );\r
1615 if (!EFI_ERROR (Status)) {\r
1616 //\r
1617 // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there\r
1618 //\r
1619 Status = Fv->ReadFile (\r
1620 Fv,\r
1621 FileGuid,\r
1622 NULL,\r
1623 &Size,\r
1624 &Type,\r
1625 &Attributes,\r
1626 &AuthenticationStatus\r
1627 );\r
1628 if (!EFI_ERROR (Status)) {\r
1629 return EFI_ALREADY_STARTED;\r
1630 }\r
1631 }\r
1632 }\r
1633\r
1634 //\r
1635 // Look for the input wanted FV file in current FV\r
1636 // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV\r
1637 //\r
1638 FindFvFile = FALSE;\r
1639 FoundFvHandle = NULL;\r
1640 Status = gBS->HandleProtocol (\r
1641 CallerImageHandle,\r
1642 &gEfiLoadedImageProtocolGuid,\r
1643 (VOID **) &LoadedImage\r
1644 );\r
1645 if (!EFI_ERROR (Status)) {\r
1646 Status = gBS->HandleProtocol (\r
1647 LoadedImage->DeviceHandle,\r
1648 &gEfiFirmwareVolume2ProtocolGuid,\r
1649 (VOID **) &Fv\r
1650 );\r
1651 if (!EFI_ERROR (Status)) {\r
1652 Status = Fv->ReadFile (\r
1653 Fv,\r
1654 FileGuid,\r
1655 NULL,\r
1656 &Size,\r
1657 &Type,\r
1658 &Attributes,\r
1659 &AuthenticationStatus\r
1660 );\r
1661 if (!EFI_ERROR (Status)) {\r
1662 FindFvFile = TRUE;\r
1663 FoundFvHandle = LoadedImage->DeviceHandle;\r
1664 }\r
1665 }\r
1666 }\r
1667 //\r
1668 // Second, if fail to find, try to enumerate all FV\r
1669 //\r
1670 if (!FindFvFile) {\r
1671 gBS->LocateHandleBuffer (\r
1672 ByProtocol,\r
1673 &gEfiFirmwareVolume2ProtocolGuid,\r
1674 NULL,\r
1675 &FvHandleCount,\r
1676 &FvHandleBuffer\r
1677 );\r
1678 for (Index = 0; Index < FvHandleCount; Index++) {\r
1679 gBS->HandleProtocol (\r
1680 FvHandleBuffer[Index],\r
1681 &gEfiFirmwareVolume2ProtocolGuid,\r
1682 (VOID **) &Fv\r
1683 );\r
1684\r
1685 Status = Fv->ReadFile (\r
1686 Fv,\r
1687 FileGuid,\r
1688 NULL,\r
1689 &Size,\r
1690 &Type,\r
1691 &Attributes,\r
1692 &AuthenticationStatus\r
1693 );\r
1694 if (EFI_ERROR (Status)) {\r
1695 //\r
1696 // Skip if input Fv file not in the FV\r
1697 //\r
1698 continue;\r
1699 }\r
1700 FindFvFile = TRUE;\r
1701 FoundFvHandle = FvHandleBuffer[Index];\r
1702 break;\r
1703 }\r
1704 }\r
1705\r
1706 if (FindFvFile) {\r
1707 //\r
1708 // Build the shell device path\r
1709 //\r
1710 NewDevicePath = DevicePathFromHandle (FoundFvHandle);\r
1711 EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid);\r
1712 NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode);\r
1713 *DevicePath = NewDevicePath;\r
1714 return EFI_SUCCESS;\r
1715 }\r
1716 return EFI_NOT_FOUND;\r
1717}\r
1718\r
1719\r
1720/**\r
1721 Read the EFI variable (VendorGuid/Name) and return a dynamically allocated\r
1722 buffer, and the size of the buffer. If failure return NULL.\r
1723\r
1724 @param Name String part of EFI variable name\r
1725 @param VendorGuid GUID part of EFI variable name\r
1726 @param VariableSize Returns the size of the EFI variable that was\r
1727 read\r
1728\r
1729 @return Dynamically allocated memory that contains a copy of the EFI variable.\r
1730 @return Caller is responsible freeing the buffer.\r
1731 @retval NULL Variable was not read\r
1732\r
1733**/\r
1734VOID *\r
1735EFIAPI\r
1736GetVariableAndSize (\r
1737 IN CHAR16 *Name,\r
1738 IN EFI_GUID *VendorGuid,\r
1739 OUT UINTN *VariableSize\r
1740 )\r
1741{\r
1742 EFI_STATUS Status;\r
1743 UINTN BufferSize;\r
1744 VOID *Buffer;\r
1745\r
1746 Buffer = NULL;\r
1747\r
1748 //\r
1749 // Pass in a zero size buffer to find the required buffer size.\r
1750 //\r
1751 BufferSize = 0;\r
1752 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1753 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1754 //\r
1755 // Allocate the buffer to return\r
1756 //\r
1757 Buffer = AllocateZeroPool (BufferSize);\r
1758 if (Buffer == NULL) {\r
1759 return NULL;\r
1760 }\r
1761 //\r
1762 // Read variable into the allocated buffer.\r
1763 //\r
1764 Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer);\r
1765 if (EFI_ERROR (Status)) {\r
1766 BufferSize = 0;\r
1767 }\r
1768 }\r
1769\r
1770 *VariableSize = BufferSize;\r
1771 return Buffer;\r
1772}\r
1773\r
1774\r
1775/**\r
1776 This function will create all handles associate with every device\r
1777 path node. If the handle associate with one device path node can not\r
1778 be created success, then still give one chance to do the dispatch,\r
1779 which load the missing drivers if possible.\r
1780\r
1781 @param DevicePathToConnect The device path which will be connected, it can\r
1782 be a multi-instance device path\r
1783\r
1784 @retval EFI_SUCCESS All handles associate with every device path\r
1785 node have been created\r
1786 @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles\r
1787 @retval EFI_NOT_FOUND Create the handle associate with one device\r
1788 path node failed\r
1789\r
1790**/\r
1791EFI_STATUS\r
1792EFIAPI\r
1793ConnectDevicePath (\r
1794 IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect\r
1795 )\r
1796{\r
1797 EFI_STATUS Status;\r
1798 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1799 EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath;\r
1800 EFI_DEVICE_PATH_PROTOCOL *Instance;\r
1801 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
1802 EFI_DEVICE_PATH_PROTOCOL *Next;\r
1803 EFI_HANDLE Handle;\r
1804 EFI_HANDLE PreviousHandle;\r
1805 UINTN Size;\r
1806\r
1807 if (DevicePathToConnect == NULL) {\r
1808 return EFI_SUCCESS;\r
1809 }\r
1810\r
1811 DevicePath = DuplicateDevicePath (DevicePathToConnect);\r
1812 CopyOfDevicePath = DevicePath;\r
1813 if (DevicePath == NULL) {\r
1814 return EFI_OUT_OF_RESOURCES;\r
1815 }\r
1816\r
1817 do {\r
1818 //\r
1819 // The outer loop handles multi instance device paths.\r
1820 // Only console variables contain multiple instance device paths.\r
1821 //\r
1822 // After this call DevicePath points to the next Instance\r
1823 //\r
1824 Instance = GetNextDevicePathInstance (&DevicePath, &Size);\r
1825 Next = Instance;\r
1826 while (!IsDevicePathEndType (Next)) {\r
1827 Next = NextDevicePathNode (Next);\r
1828 }\r
1829\r
1830 SetDevicePathEndNode (Next);\r
1831\r
1832 //\r
1833 // Start the real work of connect with RemainingDevicePath\r
1834 //\r
1835 PreviousHandle = NULL;\r
1836 do {\r
1837 //\r
1838 // Find the handle that best matches the Device Path. If it is only a\r
1839 // partial match the remaining part of the device path is returned in\r
1840 // RemainingDevicePath.\r
1841 //\r
1842 RemainingDevicePath = Instance;\r
1843 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);\r
1844\r
1845 if (!EFI_ERROR (Status)) {\r
1846 if (Handle == PreviousHandle) {\r
1847 //\r
1848 // If no forward progress is made try invoking the Dispatcher.\r
1849 // A new FV may have been added to the system an new drivers\r
1850 // may now be found.\r
1851 // Status == EFI_SUCCESS means a driver was dispatched\r
1852 // Status == EFI_NOT_FOUND means no new drivers were dispatched\r
1853 //\r
1854 Status = gDS->Dispatch ();\r
1855 }\r
1856\r
1857 if (!EFI_ERROR (Status)) {\r
1858 PreviousHandle = Handle;\r
1859 //\r
1860 // Connect all drivers that apply to Handle and RemainingDevicePath,\r
1861 // the Recursive flag is FALSE so only one level will be expanded.\r
1862 //\r
1863 // Do not check the connect status here, if the connect controller fail,\r
1864 // then still give the chance to do dispatch, because partial\r
1865 // RemainingDevicepath may be in the new FV\r
1866 //\r
1867 // 1. If the connect fail, RemainingDevicepath and handle will not\r
1868 // change, so next time will do the dispatch, then dispatch's status\r
1869 // will take effect\r
1870 // 2. If the connect success, the RemainingDevicepath and handle will\r
23d64dda 1871 // change, then avoid the dispatch, we have chance to continue the\r
b290614d 1872 // next connection\r
1873 //\r
1874 gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);\r
1875 }\r
1876 }\r
1877 //\r
1878 // Loop until RemainingDevicePath is an empty device path\r
1879 //\r
1880 } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath));\r
1881\r
1882 } while (DevicePath != NULL);\r
1883\r
1884 if (CopyOfDevicePath != NULL) {\r
1885 FreePool (CopyOfDevicePath);\r
1886 }\r
1887 //\r
1888 // All handle with DevicePath exists in the handle database\r
1889 //\r
1890 return Status;\r
1891}\r