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