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