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