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