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