]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c
Update the copyright notice format
[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
e5eed7d3
HT
4 Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.<BR>\r
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
150 FV address maybe changes for memory layout adjust from time to time, use this funciton\r
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
694 do {\r
695 VariableIndex = VariableBuffer;\r
b290614d 696 //\r
6d8ced29 697 // End flag\r
b290614d 698 //\r
6d8ced29 699 NotEnd = *(UINT32*) VariableIndex;\r
b290614d 700 //\r
6d8ced29
LG
701 // Traverse the entries containing the mapping that Controller Device Path\r
702 // to a set of Driver Device Paths within this variable.\r
b290614d 703 //\r
6d8ced29
LG
704 VariableIndex = VariableIndex + sizeof (UINT32);\r
705 while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) {\r
b290614d 706 //\r
6d8ced29
LG
707 // Check signature of this entry\r
708 //\r
709 Signature = *(UINT32 *) VariableIndex;\r
710 if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) {\r
711 Corrupted = TRUE;\r
712 break;\r
713 }\r
714 //\r
715 // Create PLATFORM_OVERRIDE_ITEM for this mapping\r
716 //\r
717 OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));\r
718 ASSERT (OverrideItem != NULL);\r
719 OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;\r
720 InitializeListHead (&OverrideItem->DriverInfoList);\r
721 VariableIndex = VariableIndex + sizeof (UINT32);\r
722 //\r
723 // Get DriverNum\r
724 //\r
725 DriverNumber = *(UINT32*) VariableIndex;\r
726 OverrideItem->DriverInfoNum = DriverNumber;\r
727 VariableIndex = VariableIndex + sizeof (UINT32);\r
728 //\r
729 // Get ControllerDevicePath[]\r
730 //\r
731 ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;\r
732 OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);\r
733 VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath);\r
734 //\r
735 // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping()\r
b290614d 736 //\r
b290614d 737 VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));\r
6d8ced29 738\r
b7a985d4 739 //\r
6d8ced29 740 // Get all DriverImageDevicePath[]\r
b7a985d4 741 //\r
6d8ced29 742 for (Index = 0; Index < DriverNumber; Index++) {\r
b290614d 743 //\r
6d8ced29
LG
744 // Create DRIVER_IMAGE_INFO for this DriverDevicePath[]\r
745 //\r
746 DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));\r
747 ASSERT (DriverImageInfo != NULL);\r
748 DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;\r
749\r
750 DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex;\r
751 DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath);\r
752 VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath);\r
753 //\r
754 // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping()\r
b290614d 755 //\r
b290614d 756 VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));\r
b290614d 757\r
6d8ced29
LG
758 InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);\r
759 }\r
760 InsertTailList (MappingDataBase, &OverrideItem->Link);\r
b290614d 761 }\r
762\r
6d8ced29
LG
763 FreePool (VariableBuffer);\r
764 if (Corrupted) {\r
765 FreeMappingDatabase (MappingDataBase);\r
766 return EFI_VOLUME_CORRUPTED;\r
b290614d 767 }\r
768\r
6d8ced29
LG
769 //\r
770 // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them.\r
771 // NotEnd indicates whether current variable is the end variable.\r
772 //\r
773 if (NotEnd != 0) {\r
774 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++);\r
775 VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);\r
776 ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);\r
777 if (VariableBuffer == NULL) {\r
778 FreeMappingDatabase (MappingDataBase);\r
779 return EFI_VOLUME_CORRUPTED;\r
780 }\r
781 }\r
b290614d 782\r
6d8ced29 783 } while (NotEnd != 0);\r
b290614d 784\r
785 return EFI_SUCCESS;\r
786}\r
787\r
6d8ced29 788\r
3012ce5c 789/**\r
6d8ced29 790 Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info.\r
3012ce5c 791\r
6d8ced29 792 @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM\r
3012ce5c 793\r
6d8ced29 794 @return The needed size number\r
3012ce5c 795\r
796**/\r
6d8ced29 797UINTN\r
3012ce5c 798EFIAPI\r
6d8ced29
LG
799GetOneItemNeededSize (\r
800 IN LIST_ENTRY *OverrideItemListIndex\r
3012ce5c 801 )\r
802{\r
6d8ced29
LG
803 UINTN NeededSize;\r
804 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
805 LIST_ENTRY *ImageInfoListIndex;\r
806 DRIVER_IMAGE_INFO *DriverImageInfo;\r
807 UINTN DevicePathSize;\r
3012ce5c 808\r
6d8ced29
LG
809 NeededSize = 0;\r
810 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
811 NeededSize += sizeof (UINT32); //UINT32 SIGNATURE;\r
812 NeededSize += sizeof (UINT32); //UINT32 DriverNum;\r
813 DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath);\r
814 NeededSize += DevicePathSize; // ControllerDevicePath\r
3012ce5c 815 //\r
6d8ced29 816 // Align the controller device path\r
3012ce5c 817 //\r
6d8ced29 818 NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));\r
b7a985d4 819 //\r
6d8ced29 820 // Traverse the Driver Info List of this Override Item\r
b7a985d4 821 //\r
6d8ced29
LG
822 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
823 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
824 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
825 DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);\r
826 NeededSize += DevicePathSize; //DriverDevicePath\r
827 //\r
828 // Align the driver image device path\r
829 //\r
830 NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1));\r
831 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
832 }\r
3012ce5c 833\r
6d8ced29 834 return NeededSize;\r
3012ce5c 835}\r
836\r
b290614d 837/**\r
6d8ced29
LG
838 Deletes all environment variable(s) that contain the override mappings from Controller Device Path to\r
839 a set of Driver Device Paths.\r
b290614d 840\r
6d8ced29 841 @retval EFI_SUCCESS Delete all variable(s) successfully.\r
b290614d 842\r
843**/\r
844EFI_STATUS\r
845EFIAPI\r
6d8ced29
LG
846DeleteOverridesVariables (\r
847 VOID\r
b290614d 848 )\r
849{\r
850 EFI_STATUS Status;\r
6d8ced29
LG
851 VOID *VariableBuffer;\r
852 UINTN VariableNum;\r
853 UINTN BufferSize;\r
854 UINTN Index;\r
855 CHAR16 OverrideVariableName[40];\r
856\r
857 //\r
858 // Get environment variable(s) number\r
859 //\r
860 VariableNum = 0;\r
861 VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize);\r
862 VariableNum++;\r
863 if (VariableBuffer == NULL) {\r
864 return EFI_NOT_FOUND;\r
b290614d 865 }\r
866 //\r
6d8ced29 867 // Check NotEnd to get all PlatDriOverX variable(s)\r
b290614d 868 //\r
6d8ced29
LG
869 while ((*(UINT32*)VariableBuffer) != 0) {\r
870 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum);\r
871 VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize);\r
872 VariableNum++;\r
873 ASSERT (VariableBuffer != NULL);\r
874 }\r
b290614d 875\r
876 //\r
6d8ced29 877 // Delete PlatDriOver and all additional variables, if exist.\r
b290614d 878 //\r
6d8ced29
LG
879 Status = gRT->SetVariable (\r
880 L"PlatDriOver",\r
881 &gEfiCallerIdGuid,\r
882 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
883 0,\r
884 NULL\r
885 );\r
886 ASSERT (!EFI_ERROR (Status));\r
887 for (Index = 1; Index < VariableNum; Index++) {\r
888 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index);\r
889 Status = gRT->SetVariable (\r
890 OverrideVariableName,\r
891 &gEfiCallerIdGuid,\r
892 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
893 0,\r
894 NULL\r
895 );\r
896 ASSERT (!EFI_ERROR (Status));\r
b290614d 897 }\r
6d8ced29 898 return EFI_SUCCESS;\r
b290614d 899}\r
900\r
901\r
902/**\r
6d8ced29 903 Save the memory mapping database into NV environment variable(s).\r
b290614d 904\r
b290614d 905 @param MappingDataBase Mapping database list entry pointer\r
b7a985d4 906\r
6d8ced29
LG
907 @retval EFI_SUCCESS Save memory mapping database successfully\r
908 @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null\r
909\r
b290614d 910**/\r
911EFI_STATUS\r
912EFIAPI\r
6d8ced29
LG
913SaveOverridesMapping (\r
914 IN LIST_ENTRY *MappingDataBase\r
b290614d 915 )\r
916{\r
6d8ced29
LG
917 EFI_STATUS Status;\r
918 VOID *VariableBuffer;\r
919 UINT8 *VariableIndex;\r
920 UINTN NumIndex;\r
921 CHAR16 OverrideVariableName[40];\r
922 UINT32 NotEnd;\r
b290614d 923 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
b290614d 924 DRIVER_IMAGE_INFO *DriverImageInfo;\r
6d8ced29
LG
925 LIST_ENTRY *OverrideItemListIndex;\r
926 LIST_ENTRY *ItemIndex;\r
927 LIST_ENTRY *ImageInfoListIndex;\r
928 UINTN VariableNeededSize;\r
929 UINT64 MaximumVariableStorageSize;\r
930 UINT64 RemainingVariableStorageSize;\r
931 UINT64 MaximumVariableSize;\r
932 UINTN OneItemNeededSize;\r
b290614d 933\r
b290614d 934 if (MappingDataBase == NULL) {\r
935 return EFI_INVALID_PARAMETER;\r
936 }\r
b7a985d4 937\r
6d8ced29
LG
938 if (IsListEmpty (MappingDataBase)) {\r
939 Status = DeleteOverridesVariables ();\r
6d8ced29
LG
940 return EFI_SUCCESS;\r
941 }\r
942\r
b290614d 943 //\r
6d8ced29 944 // Get the the maximum size of an individual EFI variable in current system\r
b290614d 945 //\r
6d8ced29
LG
946 gRT->QueryVariableInfo (\r
947 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
948 &MaximumVariableStorageSize,\r
949 &RemainingVariableStorageSize,\r
950 &MaximumVariableSize\r
951 );\r
952\r
953 NumIndex = 0;\r
b7a985d4 954 OverrideItemListIndex = GetFirstNode (MappingDataBase);\r
955 while (!IsNull (MappingDataBase, OverrideItemListIndex)) {\r
6d8ced29
LG
956 //\r
957 // Try to find the most proper variable size which <= MaximumVariableSize,\r
958 // but can contain mapping info as much as possible\r
959 //\r
960 VariableNeededSize = sizeof (UINT32); // NotEnd;\r
961 ItemIndex = OverrideItemListIndex;\r
962 NotEnd = FALSE;\r
963 //\r
964 // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size.\r
965 //\r
966 while (!IsNull (MappingDataBase, ItemIndex)) {\r
967 OneItemNeededSize = GetOneItemNeededSize (ItemIndex);\r
968 //\r
969 // If the total size exceeds the MaximumVariableSize, then we must use\r
970 // multiple variables.\r
971 //\r
972 if ((VariableNeededSize +\r
973 OneItemNeededSize +\r
974 sizeof (VARIABLE_HEADER) +\r
975 StrSize (L"PlatDriOver ")\r
976 ) >= MaximumVariableSize\r
b290614d 977 ) {\r
6d8ced29 978 NotEnd = TRUE;\r
b290614d 979 break;\r
980 }\r
6d8ced29
LG
981\r
982 VariableNeededSize += OneItemNeededSize;\r
983 ItemIndex = GetNextNode (MappingDataBase, ItemIndex);\r
984 }\r
985\r
986 if (NotEnd != 0) {\r
987 if (VariableNeededSize == sizeof (UINT32)) {\r
988 //\r
989 // If an individual EFI variable cannot contain a single Item, return error\r
990 //\r
991 return EFI_OUT_OF_RESOURCES;\r
992 }\r
b290614d 993 }\r
b290614d 994\r
b7a985d4 995 //\r
6d8ced29
LG
996 // VariableNeededSize is the most proper variable size, allocate variable buffer\r
997 // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize\r
b7a985d4 998 //\r
6d8ced29
LG
999 VariableBuffer = AllocateZeroPool (VariableNeededSize);\r
1000 ASSERT (VariableBuffer != NULL);\r
1001 ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0);\r
b290614d 1002\r
6d8ced29
LG
1003 //\r
1004 // Fill the variable buffer according to MappingDataBase\r
1005 //\r
1006 VariableIndex = VariableBuffer;\r
1007 *(UINT32 *) VariableIndex = NotEnd;\r
1008 VariableIndex += sizeof (UINT32); // pass NotEnd\r
1009 //\r
1010 // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize\r
1011 //\r
1012 while (OverrideItemListIndex != ItemIndex){\r
1013 *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE;\r
1014 VariableIndex += sizeof (UINT32); // pass SIGNATURE\r
b290614d 1015\r
6d8ced29
LG
1016 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1017 *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum;\r
1018 VariableIndex += sizeof (UINT32); // pass DriverNum\r
1019\r
1020 CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath));\r
1021 VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath\r
1022\r
1023 //\r
1024 // Align the VariableIndex since the controller device path may not be aligned\r
1025 //\r
1026 VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));\r
1027 //\r
1028 // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM\r
1029 //\r
1030 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1031 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
1032 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1033 CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath));\r
1034 VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath\r
1035 //\r
1036 // Align the VariableIndex since the driver image device path may not be aligned\r
1037 //\r
1038 VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1));\r
1039 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
b290614d 1040 }\r
b290614d 1041\r
6d8ced29 1042 OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);\r
b290614d 1043 }\r
6d8ced29
LG
1044\r
1045 ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize);\r
1046\r
1047 if (NumIndex == 0) {\r
1048 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver");\r
1049 } else {\r
1050 UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex );\r
1051 }\r
1052\r
1053 Status = gRT->SetVariable (\r
1054 OverrideVariableName,\r
1055 &gEfiCallerIdGuid,\r
1056 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
1057 VariableNeededSize,\r
1058 VariableBuffer\r
1059 );\r
1060 ASSERT (!EFI_ERROR(Status));\r
1061\r
1062 NumIndex ++;\r
1063 FreePool (VariableBuffer);\r
b290614d 1064 }\r
b290614d 1065\r
6d8ced29
LG
1066 return EFI_SUCCESS;\r
1067}\r
b290614d 1068\r
1069/**\r
6d8ced29 1070 Get the first Binding protocol which has the specific image handle.\r
b290614d 1071\r
6d8ced29
LG
1072 @param ImageHandle The Image handle\r
1073 @param BindingHandle The BindingHandle of the found Driver Binding protocol.\r
1074 If Binding protocol is not found, it is set to NULL. \r
b290614d 1075\r
6d8ced29
LG
1076 @return Pointer into the Binding Protocol interface\r
1077 @retval NULL The paramter is not valid or the binding protocol is not found.\r
b290614d 1078\r
1079**/\r
6d8ced29 1080EFI_DRIVER_BINDING_PROTOCOL *\r
b290614d 1081EFIAPI\r
6d8ced29
LG
1082GetBindingProtocolFromImageHandle (\r
1083 IN EFI_HANDLE ImageHandle,\r
1084 OUT EFI_HANDLE *BindingHandle\r
b290614d 1085 )\r
1086{\r
6d8ced29
LG
1087 EFI_STATUS Status;\r
1088 UINTN Index;\r
1089 UINTN DriverBindingHandleCount;\r
1090 EFI_HANDLE *DriverBindingHandleBuffer;\r
1091 EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;\r
b290614d 1092\r
6d8ced29
LG
1093 if (BindingHandle == NULL || ImageHandle == NULL) {\r
1094 return NULL;\r
b290614d 1095 }\r
b7a985d4 1096 //\r
6d8ced29 1097 // Get all drivers which support driver binding protocol\r
b7a985d4 1098 //\r
6d8ced29
LG
1099 DriverBindingHandleCount = 0;\r
1100 Status = gBS->LocateHandleBuffer (\r
1101 ByProtocol,\r
1102 &gEfiDriverBindingProtocolGuid,\r
1103 NULL,\r
1104 &DriverBindingHandleCount,\r
1105 &DriverBindingHandleBuffer\r
1106 );\r
1107 if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) {\r
1108 return NULL;\r
b290614d 1109 }\r
1110\r
6d8ced29
LG
1111 for (Index = 0; Index < DriverBindingHandleCount; Index++) {\r
1112 DriverBindingInterface = NULL;\r
1113 Status = gBS->OpenProtocol (\r
1114 DriverBindingHandleBuffer[Index],\r
1115 &gEfiDriverBindingProtocolGuid,\r
1116 (VOID **) &DriverBindingInterface,\r
1117 NULL,\r
1118 NULL,\r
1119 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1120 );\r
1121 if (EFI_ERROR (Status)) {\r
1122 continue;\r
1123 }\r
1124\r
1125 if (DriverBindingInterface->ImageHandle == ImageHandle) {\r
1126 *BindingHandle = DriverBindingHandleBuffer[Index];\r
1127 FreePool (DriverBindingHandleBuffer);\r
1128 return DriverBindingInterface;\r
b290614d 1129 }\r
b290614d 1130 }\r
1131\r
1132 //\r
6d8ced29 1133 // If no Driver Binding Protocol instance is found\r
b290614d 1134 //\r
6d8ced29
LG
1135 FreePool (DriverBindingHandleBuffer);\r
1136 *BindingHandle = NULL;\r
1137 return NULL;\r
1138}\r
b290614d 1139\r
6d8ced29
LG
1140/**\r
1141 Return the current TPL.\r
b290614d 1142\r
6d8ced29
LG
1143 @return Current TPL\r
1144\r
1145**/\r
1146EFI_TPL\r
1147GetCurrentTpl (\r
1148 VOID\r
1149 )\r
1150{\r
1151 EFI_TPL Tpl;\r
1152\r
1153 Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
1154 gBS->RestoreTPL (Tpl);\r
1155\r
1156 return Tpl;\r
b290614d 1157}\r
1158\r
1159\r
1160/**\r
6d8ced29
LG
1161 Retrieves the image handle of the platform override driver for a controller in\r
1162 the system from the memory mapping database.\r
b290614d 1163\r
6d8ced29
LG
1164 @param ControllerHandle The device handle of the controller to check if\r
1165 a driver override exists.\r
1166 @param DriverImageHandle On input, the previously returnd driver image handle.\r
1167 On output, a pointer to the next driver handle.\r
1168 Passing in a pointer to NULL, will return the\r
1169 first driver handle for ControllerHandle.\r
b290614d 1170 @param MappingDataBase Mapping database list entry pointer\r
6d8ced29
LG
1171 @param CallerImageHandle The caller driver's image handle, for\r
1172 UpdateFvFileDevicePath use.\r
b290614d 1173\r
6d8ced29
LG
1174 @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not\r
1175 a valid handle. Or DriverImagePath is not a\r
1176 device path that was returned on a previous call\r
1177 to GetDriverPath().\r
1178 @retval EFI_NOT_FOUND A driver override for ControllerHandle was not\r
1179 found.\r
1180 @retval EFI_UNSUPPORTED The operation is not supported.\r
1181 @retval EFI_SUCCESS The driver override for ControllerHandle was\r
1182 returned in DriverImagePath.\r
b290614d 1183\r
1184**/\r
1185EFI_STATUS\r
1186EFIAPI\r
6d8ced29
LG
1187GetDriverFromMapping (\r
1188 IN EFI_HANDLE ControllerHandle,\r
1189 IN OUT EFI_HANDLE *DriverImageHandle,\r
1190 IN LIST_ENTRY *MappingDataBase,\r
1191 IN EFI_HANDLE CallerImageHandle\r
b290614d 1192 )\r
1193{\r
1194 EFI_STATUS Status;\r
6d8ced29
LG
1195 EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;\r
1196 BOOLEAN ControllerFound;\r
1197 BOOLEAN ImageFound;\r
1198 EFI_HANDLE *ImageHandleBuffer;\r
1199 UINTN ImageHandleCount;\r
1200 UINTN Index;\r
1201 EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;\r
1202 EFI_HANDLE DriverBindingHandle;\r
1203 BOOLEAN FoundLastReturned;\r
b290614d 1204 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
b290614d 1205 DRIVER_IMAGE_INFO *DriverImageInfo;\r
6d8ced29
LG
1206 LIST_ENTRY *OverrideItemListIndex;\r
1207 LIST_ENTRY *ImageInfoListIndex;\r
1208 EFI_DEVICE_PATH_PROTOCOL *TempDriverImagePath;\r
1209 EFI_HANDLE ImageHandle;\r
1210 EFI_HANDLE Handle;\r
1211 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
1212 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
b290614d 1213 UINTN DevicePathSize;\r
1214\r
6d8ced29
LG
1215 //\r
1216 // Check that ControllerHandle is a valid handle\r
1217 //\r
1218 if (ControllerHandle == NULL) {\r
b290614d 1219 return EFI_INVALID_PARAMETER;\r
1220 }\r
b7a985d4 1221 //\r
6d8ced29 1222 // Get the device path of ControllerHandle\r
b7a985d4 1223 //\r
6d8ced29
LG
1224 Status = gBS->HandleProtocol (\r
1225 ControllerHandle,\r
1226 &gEfiDevicePathProtocolGuid,\r
1227 (VOID **) &ControllerDevicePath\r
1228 );\r
1229 if (EFI_ERROR (Status) || ControllerDevicePath == NULL) {\r
1230 return EFI_INVALID_PARAMETER;\r
b290614d 1231 }\r
1232\r
1233 //\r
1234 // Search ControllerDevicePath in MappingDataBase\r
1235 //\r
b290614d 1236 OverrideItem = NULL;\r
6d8ced29
LG
1237 ControllerFound = FALSE;\r
1238 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1239\r
b7a985d4 1240 OverrideItemListIndex = GetFirstNode (MappingDataBase);\r
1241 while (!IsNull (MappingDataBase, OverrideItemListIndex)) {\r
b290614d 1242 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
b290614d 1243 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1244 if (CompareMem (\r
1245 ControllerDevicePath,\r
1246 OverrideItem->ControllerDevicePath,\r
b7a985d4 1247 DevicePathSize\r
b290614d 1248 ) == 0\r
1249 ) {\r
6d8ced29 1250 ControllerFound = TRUE;\r
b290614d 1251 break;\r
1252 }\r
1253 }\r
b7a985d4 1254 OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);\r
b290614d 1255 }\r
1256\r
6d8ced29
LG
1257 if (!ControllerFound) {\r
1258 return EFI_NOT_FOUND;\r
1259 }\r
1260 //\r
1261 // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle.\r
1262 // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath().\r
1263 //\r
1264 if (*DriverImageHandle != NULL) {\r
1265 if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) {\r
1266 return EFI_INVALID_PARAMETER;\r
1267 }\r
1268 }\r
1269 //\r
1270 // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally,\r
1271 // so should check whether there is a dead loop.\r
1272 // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call,\r
1273 // and check the controller device path whether appear again during the GetDriverPath() call.\r
1274 //\r
1275 if (CheckExistInStack (OverrideItem->ControllerDevicePath)) {\r
1276 //\r
1277 // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice\r
1278 //\r
1279 return EFI_UNSUPPORTED;\r
1280 }\r
1281 PushDevPathStack (OverrideItem->ControllerDevicePath);\r
b7a985d4 1282\r
6d8ced29
LG
1283 //\r
1284 // Check every override driver, try to load and start them\r
1285 //\r
b7a985d4 1286 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1287 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
b290614d 1288 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
6d8ced29 1289 if (DriverImageInfo->ImageHandle == NULL) {\r
b7a985d4 1290 //\r
6d8ced29 1291 // Skip if the image is unloadable or unstartable\r
b7a985d4 1292 //\r
6d8ced29
LG
1293 if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) {\r
1294 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
1295 //\r
1296 // If the image device path contains an FV node, check the FV file device path is valid.\r
1297 // If it is invalid, try to return the valid device path.\r
1298 // FV address maybe changes for memory layout adjust from time to time,\r
1299 // use this funciton could promise the FV file device path is right.\r
1300 //\r
1301 Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle);\r
1302 if (!EFI_ERROR (Status)) {\r
1303 FreePool (DriverImageInfo->DriverImagePath);\r
1304 DriverImageInfo->DriverImagePath = TempDriverImagePath;\r
b290614d 1305 }\r
6d8ced29
LG
1306 //\r
1307 // Get all Loaded Image protocol to check whether the driver image has been loaded and started\r
1308 //\r
1309 ImageFound = FALSE;\r
1310 ImageHandleCount = 0;\r
1311 Status = gBS->LocateHandleBuffer (\r
1312 ByProtocol,\r
1313 &gEfiLoadedImageProtocolGuid,\r
1314 NULL,\r
1315 &ImageHandleCount,\r
1316 &ImageHandleBuffer\r
1317 );\r
1318 if (EFI_ERROR (Status) || (ImageHandleCount == 0)) {\r
1319 return EFI_NOT_FOUND;\r
1320 }\r
1321\r
1322 for(Index = 0; Index < ImageHandleCount; Index ++) {\r
1323 //\r
1324 // Get the EFI Loaded Image Device Path Protocol\r
1325 //\r
1326 LoadedImageDevicePath = NULL;\r
1327 Status = gBS->HandleProtocol (\r
1328 ImageHandleBuffer[Index],\r
1329 &gEfiLoadedImageDevicePathProtocolGuid,\r
1330 (VOID **) &LoadedImageDevicePath\r
1331 );\r
1332 if (EFI_ERROR (Status)) {\r
1333 //\r
1334 // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed.\r
1335 //\r
1336 continue;\r
1337 }\r
1338\r
1339 DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath);\r
1340 if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) {\r
1341 if (CompareMem (\r
1342 DriverImageInfo->DriverImagePath,\r
1343 LoadedImageDevicePath,\r
1344 GetDevicePathSize (LoadedImageDevicePath)\r
1345 ) == 0\r
1346 ) {\r
1347 ImageFound = TRUE;\r
1348 break;\r
1349 }\r
1350 }\r
1351 }\r
1352\r
1353 if (ImageFound) {\r
1354 //\r
1355 // Find its related driver binding protocol\r
1356 // Driver binding handle may be different with its driver's Image Handle.\r
1357 //\r
1358 DriverBindingHandle = NULL;\r
1359 DriverBinding = GetBindingProtocolFromImageHandle (\r
1360 ImageHandleBuffer[Index],\r
1361 &DriverBindingHandle\r
1362 );\r
1363 ASSERT (DriverBinding != NULL);\r
1364 DriverImageInfo->ImageHandle = ImageHandleBuffer[Index];\r
1365 } else if (GetCurrentTpl() <= TPL_CALLBACK){\r
1366 //\r
1367 // The driver image has not been loaded and started. Try to load and start it now.\r
1368 // Try to connect all device in the driver image path.\r
1369 //\r
1370 // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but\r
1371 // since many device need to be connected in CALLBACK level environment( e.g. Usb devices )\r
1372 // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit\r
1373 // to use LoadImage() and StartImage() in CALLBACK TPL.\r
1374 //\r
1375 Status = ConnectDevicePath (DriverImageInfo->DriverImagePath);\r
1376 //\r
1377 // check whether it points to a PCI Option Rom image,\r
1378 // and try to use bus override protocol to get its first option rom image driver\r
1379 //\r
1380 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
1381 gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);\r
1382 //\r
1383 // Get the Bus Specific Driver Override Protocol instance on the Controller Handle\r
1384 //\r
1385 Status = gBS->HandleProtocol(\r
1386 Handle,\r
1387 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
1388 (VOID **) &BusSpecificDriverOverride\r
1389 );\r
1390 if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) {\r
1391 ImageHandle = NULL;\r
1392 Status = BusSpecificDriverOverride->GetDriver (\r
1393 BusSpecificDriverOverride,\r
1394 &ImageHandle\r
1395 );\r
1396 if (!EFI_ERROR (Status)) {\r
1397 //\r
1398 // Find its related driver binding protocol\r
1399 // Driver binding handle may be different with its driver's Image handle\r
1400 //\r
1401 DriverBindingHandle = NULL;\r
1402 DriverBinding = GetBindingProtocolFromImageHandle (\r
1403 ImageHandle,\r
1404 &DriverBindingHandle\r
1405 );\r
1406 ASSERT (DriverBinding != NULL);\r
1407 DriverImageInfo->ImageHandle = ImageHandle;\r
1408 }\r
1409 }\r
1410 //\r
1411 // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver.\r
1412 // Only file path media or FwVol Device Path Node remain if all device is connected\r
1413 //\r
1414 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
1415 gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle);\r
1416 if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) &&\r
1417 (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) ||\r
1418 (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL)\r
1419 ) {\r
1420 //\r
1421 // Try to load the driver\r
1422 //\r
1423 TempDriverImagePath = DriverImageInfo->DriverImagePath;\r
1424 Status = gBS->LoadImage (\r
1425 FALSE,\r
1426 CallerImageHandle,\r
1427 TempDriverImagePath,\r
1428 NULL,\r
1429 0,\r
1430 &ImageHandle\r
1431 );\r
1432 if (!EFI_ERROR (Status)) {\r
1433 //\r
1434 // Try to start the driver\r
1435 //\r
1436 Status = gBS->StartImage (ImageHandle, NULL, NULL);\r
1437 if (EFI_ERROR (Status)){\r
1438 DriverImageInfo->UnStartable = TRUE;\r
1439 DriverImageInfo->ImageHandle = NULL;\r
1440 } else {\r
1441 //\r
1442 // Find its related driver binding protocol\r
1443 // Driver binding handle may be different with its driver's Image handle\r
1444 //\r
1445 DriverBindingHandle = NULL;\r
1446 DriverBinding = GetBindingProtocolFromImageHandle (\r
1447 ImageHandle,\r
1448 &DriverBindingHandle\r
1449 );\r
1450 ASSERT (DriverBinding != NULL);\r
1451 DriverImageInfo->ImageHandle = ImageHandle;\r
1452 }\r
1453 } else {\r
1454 DriverImageInfo->UnLoadable = TRUE;\r
1455 DriverImageInfo->ImageHandle = NULL;\r
1456 }\r
1457 }\r
1458 }\r
1459 FreePool (ImageHandleBuffer);\r
1460 }\r
b290614d 1461 }\r
6d8ced29 1462 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
b290614d 1463 }\r
b7a985d4 1464 //\r
6d8ced29 1465 // Finish try to load and start the override driver of a controller, popup the controller's device path\r
b7a985d4 1466 //\r
6d8ced29 1467 PopDevPathStack (NULL);\r
b290614d 1468\r
b7a985d4 1469 //\r
6d8ced29 1470 // return the DriverImageHandle for ControllerHandle\r
b7a985d4 1471 //\r
6d8ced29
LG
1472 FoundLastReturned = FALSE;\r
1473 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1474 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
1475 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1476 if (DriverImageInfo->ImageHandle != NULL) {\r
1477 if ((*DriverImageHandle == NULL) || FoundLastReturned) {\r
1478 //\r
1479 // If DriverImageHandle is NULL, then we just need to return the first driver.\r
1480 // If FoundLastReturned, this means we have just encountered the previously returned driver.\r
1481 // For both cases, we just return the image handle of this driver.\r
1482 //\r
1483 OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle;\r
1484 *DriverImageHandle = DriverImageInfo->ImageHandle;\r
1485 return EFI_SUCCESS;\r
1486 } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){\r
1487 //\r
1488 // We have found the previously returned driver.\r
1489 //\r
1490 FoundLastReturned = TRUE;\r
b290614d 1491 }\r
1492 }\r
6d8ced29 1493 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
b290614d 1494 }\r
1495\r
6d8ced29 1496 return EFI_NOT_FOUND;\r
b290614d 1497}\r
1498\r
1499\r
1500/**\r
6d8ced29
LG
1501 Check mapping database whether already has the mapping info which\r
1502 records the input Controller to input DriverImage.\r
b290614d 1503\r
6d8ced29
LG
1504 @param ControllerDevicePath The controller device path is to be check.\r
1505 @param DriverImageDevicePath The driver image device path is to be check.\r
1506 @param MappingDataBase Mapping database list entry pointer\r
1507 @param DriverInfoNum the controller's total override driver number\r
1508 @param DriverImageNO The driver order number for the input DriverImage.\r
1509 If the DriverImageDevicePath is NULL, DriverImageNO is not set.\r
b290614d 1510\r
6d8ced29
LG
1511 @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL.\r
1512 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or\r
1513 DriverImageDevicePath is not found in the found DriverImage Info list. \r
1514 @retval EFI_SUCCESS The controller's total override driver number and \r
1515 input DriverImage's order number is correctly return.\r
b290614d 1516**/\r
1517EFI_STATUS\r
1518EFIAPI\r
6d8ced29
LG
1519CheckMapping (\r
1520 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
1521 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL,\r
1522 IN LIST_ENTRY *MappingDataBase,\r
1523 OUT UINT32 *DriverInfoNum OPTIONAL,\r
1524 OUT UINT32 *DriverImageNO OPTIONAL\r
b290614d 1525 )\r
1526{\r
6d8ced29
LG
1527 LIST_ENTRY *OverrideItemListIndex;\r
1528 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
1529 LIST_ENTRY *ImageInfoListIndex;\r
1530 DRIVER_IMAGE_INFO *DriverImageInfo;\r
1531 BOOLEAN Found;\r
1532 UINT32 ImageNO;\r
1533 UINTN DevicePathSize;\r
b7a985d4 1534\r
6d8ced29 1535 if (ControllerDevicePath == NULL) {\r
b7a985d4 1536 return EFI_INVALID_PARAMETER;\r
1537 }\r
6d8ced29 1538 if (MappingDataBase == NULL) {\r
b290614d 1539 return EFI_INVALID_PARAMETER;\r
1540 }\r
1541\r
1542 //\r
6d8ced29 1543 // Search ControllerDevicePath in MappingDataBase\r
b290614d 1544 //\r
6d8ced29
LG
1545 Found = FALSE;\r
1546 OverrideItem = NULL;\r
1547 OverrideItemListIndex = GetFirstNode (MappingDataBase);\r
1548 while (!IsNull (MappingDataBase, OverrideItemListIndex)) {\r
1549 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1550 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1551 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1552 if (CompareMem (\r
1553 ControllerDevicePath,\r
1554 OverrideItem->ControllerDevicePath,\r
1555 DevicePathSize\r
1556 ) == 0\r
1557 ) {\r
1558 Found = TRUE;\r
1559 break;\r
1560 }\r
b290614d 1561 }\r
6d8ced29 1562 OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);\r
b290614d 1563 }\r
1564\r
6d8ced29 1565 if (!Found) {\r
b290614d 1566 //\r
6d8ced29 1567 // ControllerDevicePath is not in MappingDataBase\r
b290614d 1568 //\r
6d8ced29 1569 return EFI_NOT_FOUND;\r
b290614d 1570 }\r
1571\r
6d8ced29
LG
1572 ASSERT (OverrideItem->DriverInfoNum != 0);\r
1573 if (DriverInfoNum != NULL) {\r
1574 *DriverInfoNum = OverrideItem->DriverInfoNum;\r
b290614d 1575 }\r
1576\r
1577 //\r
6d8ced29
LG
1578 // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath\r
1579 // in the controller's Driver Image Info List\r
b290614d 1580 //\r
6d8ced29
LG
1581 if (DriverImageDevicePath == NULL) {\r
1582 return EFI_SUCCESS;\r
b290614d 1583 }\r
1584 //\r
6d8ced29 1585 // return the DriverImageHandle for ControllerHandle\r
b290614d 1586 //\r
6d8ced29
LG
1587 ImageNO = 0;\r
1588 Found = FALSE;\r
1589 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1590 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
1591 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1592 ImageNO++;\r
1593 DevicePathSize = GetDevicePathSize (DriverImageDevicePath);\r
1594 if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {\r
1595 if (CompareMem (\r
1596 DriverImageDevicePath,\r
1597 DriverImageInfo->DriverImagePath,\r
1598 GetDevicePathSize (DriverImageInfo->DriverImagePath)\r
1599 ) == 0\r
1600 ) {\r
1601 Found = TRUE;\r
1602 break;\r
b290614d 1603 }\r
b290614d 1604 }\r
6d8ced29 1605 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
b290614d 1606 }\r
1607\r
6d8ced29 1608 if (!Found) {\r
b290614d 1609 //\r
6d8ced29 1610 // DriverImageDevicePath is not found in the controller's Driver Image Info List\r
b290614d 1611 //\r
6d8ced29
LG
1612 return EFI_NOT_FOUND;\r
1613 } else {\r
1614 if (DriverImageNO != NULL) {\r
1615 *DriverImageNO = ImageNO;\r
1616 }\r
b290614d 1617 return EFI_SUCCESS;\r
1618 }\r
b290614d 1619}\r
1620\r
1621\r
1622/**\r
6d8ced29
LG
1623 Insert a driver image as a controller's override driver into the mapping database.\r
1624 The driver image's order number is indicated by DriverImageNO.\r
b290614d 1625\r
6d8ced29
LG
1626 @param ControllerDevicePath The controller device path need to add a\r
1627 override driver image item\r
1628 @param DriverImageDevicePath The driver image device path need to be insert\r
1629 @param MappingDataBase Mapping database list entry pointer\r
1630 @param DriverImageNO The inserted order number. If this number is taken, \r
1631 the larger available number will be used.\r
b290614d 1632\r
6d8ced29
LG
1633 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL\r
1634 or MappingDataBase is NULL\r
1635 @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been \r
1636 recorded into the mapping database.\r
1637 @retval EFI_SUCCESS The Controller and DriverImage are inserted into \r
1638 the mapping database successfully.\r
b290614d 1639\r
1640**/\r
6d8ced29 1641EFI_STATUS\r
b290614d 1642EFIAPI\r
6d8ced29
LG
1643InsertDriverImage (\r
1644 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
1645 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,\r
1646 IN LIST_ENTRY *MappingDataBase,\r
1647 IN UINT32 DriverImageNO\r
b290614d 1648 )\r
1649{\r
6d8ced29
LG
1650 EFI_STATUS Status;\r
1651 LIST_ENTRY *OverrideItemListIndex;\r
1652 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
1653 LIST_ENTRY *ImageInfoListIndex;\r
1654 DRIVER_IMAGE_INFO *DriverImageInfo;\r
1655 BOOLEAN Found;\r
1656 UINT32 ImageNO;\r
1657 UINTN DevicePathSize;\r
b290614d 1658\r
6d8ced29
LG
1659 if (ControllerDevicePath == NULL) {\r
1660 return EFI_INVALID_PARAMETER;\r
1661 }\r
1662 if (DriverImageDevicePath == NULL) {\r
1663 return EFI_INVALID_PARAMETER;\r
1664 }\r
1665 if (MappingDataBase == NULL) {\r
1666 return EFI_INVALID_PARAMETER;\r
1667 }\r
1668\r
1669 //\r
1670 // If the driver is already in the controller's Driver Image Info List,\r
1671 // just return EFI_ALREADY_STARTED.\r
1672 //\r
1673 Status = CheckMapping (\r
1674 ControllerDevicePath,\r
1675 DriverImageDevicePath,\r
1676 MappingDataBase,\r
1677 NULL,\r
1678 NULL\r
1679 );\r
1680 if (Status == EFI_SUCCESS) {\r
1681 return EFI_ALREADY_STARTED;\r
1682 }\r
1683\r
1684 //\r
1685 // Search the input ControllerDevicePath in MappingDataBase\r
1686 //\r
1687 Found = FALSE;\r
1688 OverrideItem = NULL;\r
1689 OverrideItemListIndex = GetFirstNode (MappingDataBase);\r
1690 while (!IsNull (MappingDataBase, OverrideItemListIndex)) {\r
1691 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1692 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1693 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1694 if (CompareMem (\r
1695 ControllerDevicePath,\r
1696 OverrideItem->ControllerDevicePath,\r
1697 DevicePathSize\r
1698 ) == 0\r
1699 ) {\r
1700 Found = TRUE;\r
1701 break;\r
1702 }\r
1703 }\r
1704 OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);\r
1705 }\r
1706 //\r
1707 // If cannot find, this is a new controller item\r
1708 // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base\r
1709 //\r
1710 if (!Found) {\r
1711 OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM));\r
1712 ASSERT (OverrideItem != NULL);\r
1713 OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE;\r
1714 OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath);\r
1715 InitializeListHead (&OverrideItem->DriverInfoList);\r
1716 InsertTailList (MappingDataBase, &OverrideItem->Link);\r
1717 }\r
b290614d 1718\r
1719 //\r
6d8ced29 1720 // Prepare the driver image related DRIVER_IMAGE_INFO structure.\r
b290614d 1721 //\r
6d8ced29
LG
1722 DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO));\r
1723 ASSERT (DriverImageInfo != NULL);\r
1724 DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE;\r
1725 DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath);\r
1726 //\r
1727 // Find the driver image wanted order location\r
1728 //\r
1729 ImageNO = 0;\r
1730 Found = FALSE;\r
1731 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1732 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
1733 if (ImageNO == (DriverImageNO - 1)) {\r
1734 //\r
1735 // find the wanted order location, insert it\r
1736 //\r
1737 InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link);\r
1738 OverrideItem->DriverInfoNum ++;\r
1739 Found = TRUE;\r
1740 break;\r
b290614d 1741 }\r
6d8ced29
LG
1742 ImageNO++;\r
1743 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
1744 }\r
1745\r
1746 if (!Found) {\r
b290614d 1747 //\r
6d8ced29 1748 // if not find the wanted order location, add it as last item of the controller mapping item\r
b290614d 1749 //\r
6d8ced29
LG
1750 InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link);\r
1751 OverrideItem->DriverInfoNum ++;\r
b290614d 1752 }\r
1753\r
6d8ced29 1754 return EFI_SUCCESS;\r
b290614d 1755}\r
1756\r
1757\r
1758/**\r
6d8ced29 1759 Delete a controller's override driver from the mapping database.\r
b290614d 1760\r
6d8ced29
LG
1761 @param ControllerDevicePath The controller device path will be deleted \r
1762 when all drivers images on it are removed.\r
1763 @param DriverImageDevicePath The driver image device path will be delete.\r
1764 If NULL, all driver image will be delete.\r
1765 @param MappingDataBase Mapping database list entry pointer\r
b290614d 1766\r
6d8ced29
LG
1767 @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL\r
1768 @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or\r
1769 DriverImageDevicePath is not found in the found DriverImage Info list. \r
1770 @retval EFI_SUCCESS Delete the specified driver successfully.\r
b290614d 1771\r
1772**/\r
1773EFI_STATUS\r
1774EFIAPI\r
6d8ced29
LG
1775DeleteDriverImage (\r
1776 IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath,\r
1777 IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath,\r
1778 IN LIST_ENTRY *MappingDataBase\r
b290614d 1779 )\r
1780{\r
6d8ced29
LG
1781 EFI_STATUS Status;\r
1782 LIST_ENTRY *OverrideItemListIndex;\r
1783 PLATFORM_OVERRIDE_ITEM *OverrideItem;\r
1784 LIST_ENTRY *ImageInfoListIndex;\r
1785 DRIVER_IMAGE_INFO *DriverImageInfo;\r
1786 BOOLEAN Found;\r
1787 UINTN DevicePathSize;\r
b290614d 1788\r
6d8ced29
LG
1789 if (ControllerDevicePath == NULL) {\r
1790 return EFI_INVALID_PARAMETER;\r
b290614d 1791 }\r
1792\r
6d8ced29
LG
1793 if (MappingDataBase == NULL) {\r
1794 return EFI_INVALID_PARAMETER;\r
b290614d 1795 }\r
1796\r
6d8ced29
LG
1797 //\r
1798 // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND.\r
1799 //\r
1800 Status = CheckMapping (\r
1801 ControllerDevicePath,\r
1802 DriverImageDevicePath,\r
1803 MappingDataBase,\r
1804 NULL,\r
1805 NULL\r
1806 );\r
1807 if (EFI_ERROR (Status)) {\r
1808 return EFI_NOT_FOUND;\r
1809 }\r
81464cf1 1810\r
6d8ced29
LG
1811 //\r
1812 // Search ControllerDevicePath in MappingDataBase\r
1813 //\r
1814 Found = FALSE;\r
1815 OverrideItem = NULL;\r
1816 OverrideItemListIndex = GetFirstNode (MappingDataBase);\r
1817 while (!IsNull (MappingDataBase, OverrideItemListIndex)) {\r
1818 OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE);\r
1819 DevicePathSize = GetDevicePathSize (ControllerDevicePath);\r
1820 if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) {\r
1821 if (CompareMem (\r
1822 ControllerDevicePath,\r
1823 OverrideItem->ControllerDevicePath,\r
1824 DevicePathSize\r
1825 ) == 0\r
1826 ) {\r
1827 Found = TRUE;\r
1828 break;\r
1829 }\r
b290614d 1830 }\r
6d8ced29
LG
1831 OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex);\r
1832 }\r
b290614d 1833\r
6d8ced29
LG
1834 ASSERT (Found);\r
1835 ASSERT (OverrideItem->DriverInfoNum != 0);\r
b290614d 1836\r
6d8ced29
LG
1837 Found = FALSE;\r
1838 ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList);\r
1839 while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) {\r
1840 DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE);\r
1841 ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex);\r
1842 if (DriverImageDevicePath != NULL) {\r
b290614d 1843 //\r
6d8ced29 1844 // Search for the specified DriverImageDevicePath and remove it, then break.\r
b290614d 1845 //\r
6d8ced29
LG
1846 DevicePathSize = GetDevicePathSize (DriverImageDevicePath);\r
1847 if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) {\r
1848 if (CompareMem (\r
1849 DriverImageDevicePath,\r
1850 DriverImageInfo->DriverImagePath,\r
1851 GetDevicePathSize (DriverImageInfo->DriverImagePath)\r
1852 ) == 0\r
1853 ) {\r
1854 Found = TRUE;\r
1855 FreePool(DriverImageInfo->DriverImagePath);\r
1856 RemoveEntryList (&DriverImageInfo->Link);\r
1857 OverrideItem->DriverInfoNum --;\r
1858 break;\r
b290614d 1859 }\r
1860 }\r
6d8ced29 1861 } else {\r
b290614d 1862 //\r
6d8ced29 1863 // Remove all existing driver image info entries, so no break here.\r
b290614d 1864 //\r
6d8ced29
LG
1865 Found = TRUE;\r
1866 FreePool(DriverImageInfo->DriverImagePath);\r
1867 RemoveEntryList (&DriverImageInfo->Link);\r
1868 OverrideItem->DriverInfoNum --;\r
1869 }\r
1870 }\r
b290614d 1871\r
6d8ced29
LG
1872 //\r
1873 // Confirm all driver image info entries have been removed,\r
1874 // if DriverImageDevicePath is NULL.\r
1875 //\r
1876 if (DriverImageDevicePath == NULL) {\r
1877 ASSERT (OverrideItem->DriverInfoNum == 0);\r
b290614d 1878 }\r
1879 //\r
6d8ced29 1880 // If Override Item has no driver image info entry, then delete this item.\r
b290614d 1881 //\r
6d8ced29
LG
1882 if (OverrideItem->DriverInfoNum == 0) {\r
1883 FreePool(OverrideItem->ControllerDevicePath);\r
1884 RemoveEntryList (&OverrideItem->Link);\r
1885 FreePool (OverrideItem);\r
1886 }\r
1887\r
1888 if (!Found) {\r
1889 //\r
1890 // DriverImageDevicePath is not NULL and cannot be found in the controller's\r
1891 // driver image info list.\r
1892 //\r
1893 return EFI_NOT_FOUND;\r
1894 }\r
1895\r
1896 return EFI_SUCCESS;\r
b290614d 1897}\r