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