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