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