]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PlatformDriverOverride/PlatOverMngr/PlatOverMngr.c
1. Create PlatformDriverOverride in Universal directory.
[mirror_edk2.git] / MdeModulePkg / Universal / PlatformDriverOverride / PlatOverMngr / PlatOverMngr.c
CommitLineData
a6f164a7 1/** @file\r
2\r
3Copyright (c) 2007 - 2008, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 PlatOverMngr.c\r
15\r
16Abstract:\r
17\r
18 A UI driver to offer a UI interface in device manager to let user configue\r
19 platform override protocol to override the default algorithm for matching\r
20 drivers to controllers.\r
21\r
22 The main flow:\r
23 1. The UI driver dynamicly locate all controller device path.\r
24 2. The UI driver dynamicly locate all drivers which support binding protocol.\r
25 3. The UI driver export and dynamicly update two menu to let user select the\r
26 mapping between drivers to controllers.\r
27 4. The UI driver save all the mapping info in NV variables which will be consumed\r
28 by platform override protocol driver to publish the platform override protocol.\r
29\r
30**/\r
31\r
32#include "PlatOverMngr.h"\r
33\r
34STATIC EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;\r
35\r
36STATIC LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);\r
37\r
38STATIC EFI_HANDLE *mDevicePathHandleBuffer;\r
39STATIC EFI_HANDLE *mDriverImageHandleBuffer;\r
40STATIC EFI_HANDLE mSelectedCtrDPHandle;\r
41\r
42STATIC CFG_PROTOCOL_INVOKER_CHOICE mChoice[MAX_CHOICE_NUM];\r
43\r
44STATIC UINTN mSelectedCtrIndex;\r
45STATIC EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];\r
46\r
47STATIC UINTN mDriverImageHandleCount;\r
48STATIC EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM];\r
49STATIC EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM];\r
50STATIC EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM];\r
51STATIC EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM];\r
52STATIC UINTN mSelectedDriverImageNum;\r
53STATIC UINTN mLastSavedDriverImageNum;\r
54STATIC CHAR8 mLanguage[RFC_3066_ENTRY_SIZE];\r
55STATIC UINT16 mCurrentPage;\r
56\r
57/**\r
58 The driver Entry Point. The funciton will export a disk device class formset and\r
59 its callback function to hii database.\r
60\r
61 @param ImageHandle The firmware allocated handle for the EFI image.\r
62 @param SystemTable A pointer to the EFI System Table.\r
63\r
64 @retval EFI_SUCCESS The entry point is executed successfully.\r
65 @retval other Some error occurs when executing this entry point.\r
66\r
67**/\r
68EFI_STATUS\r
69EFIAPI\r
70PlatOverMngrInit (\r
71 IN EFI_HANDLE ImageHandle,\r
72 IN EFI_SYSTEM_TABLE *SystemTable\r
73 )\r
74{\r
75 EFI_STATUS Status;\r
76 EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
77 EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
78 EFI_CALLBACK_INFO *CallbackInfo;\r
79 EFI_HANDLE DriverHandle;\r
80 EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
81\r
82 //\r
83 // There should only be one HII protocol\r
84 //\r
85 Status = gBS->LocateProtocol (\r
86 &gEfiHiiDatabaseProtocolGuid,\r
87 NULL,\r
88 (VOID **) &HiiDatabase\r
89 );\r
90 if (EFI_ERROR (Status)) {\r
91 return Status ;\r
92 }\r
93\r
94\r
95 //\r
96 // There should only be one Form Configuration protocol\r
97 //\r
98 Status = gBS->LocateProtocol (\r
99 &gEfiFormBrowser2ProtocolGuid,\r
100 NULL,\r
101 (VOID **) &FormBrowser2\r
102 );\r
103 if (EFI_ERROR (Status)) {\r
104 return Status;;\r
105 }\r
106\r
107\r
108 CallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));\r
109 if (CallbackInfo == NULL) {\r
110 return EFI_BAD_BUFFER_SIZE;\r
111 }\r
112\r
113 CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;\r
114 CallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;\r
115 CallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig;\r
116 CallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback;\r
117\r
118 //\r
119 // Create driver handle used by HII database\r
120 //\r
121 Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
122 if (EFI_ERROR (Status)) {\r
123 return Status;\r
124 }\r
125 CallbackInfo->DriverHandle = DriverHandle;\r
126\r
127 //\r
128 // Install Config Access protocol to driver handle\r
129 //\r
130 Status = gBS->InstallProtocolInterface (\r
131 &DriverHandle,\r
132 &gEfiHiiConfigAccessProtocolGuid,\r
133 EFI_NATIVE_INTERFACE,\r
134 &CallbackInfo->ConfigAccess\r
135 );\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139\r
140 //\r
141 // Publish our HII data\r
142 //\r
143 PackageList = HiiLibPreparePackageList (\r
144 2,\r
145 &mPlatformOverridesManagerGuid,\r
146 VfrBin,\r
147 PlatOverMngrStrings\r
148 );\r
149 ASSERT (PackageList != NULL);\r
150\r
151 Status = HiiDatabase->NewPackageList (\r
152 HiiDatabase,\r
153 PackageList,\r
154 DriverHandle,\r
155 &CallbackInfo->RegisteredHandle\r
156 );\r
157 gBS->FreePool (PackageList);\r
158\r
159 //\r
160 // Locate ConfigRouting protocol\r
161 //\r
162 Status = gBS->LocateProtocol (\r
163 &gEfiHiiConfigRoutingProtocolGuid,\r
164 NULL,\r
165 (VOID **) &CallbackInfo->HiiConfigRouting\r
166 );\r
167 if (EFI_ERROR (Status)) {\r
168 return Status;\r
169 }\r
170\r
171 //\r
172 // Clear all the globle variable\r
173 //\r
174 mDriverImageHandleCount = 0;\r
175 mCurrentPage = 0;\r
176 ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
177 ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
178 ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
179 ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));\r
180\r
181 //\r
182 // Show the page\r
183 //\r
184 Status = FormBrowser2->SendForm (\r
185 FormBrowser2,\r
186 &CallbackInfo->RegisteredHandle,\r
187 1,\r
188 NULL,\r
189 0,\r
190 NULL,\r
191 NULL\r
192 );\r
193\r
194 Status = HiiDatabase->RemovePackageList (HiiDatabase, CallbackInfo->RegisteredHandle);\r
195 if (EFI_ERROR (Status)) {\r
196 return Status;\r
197 }\r
198\r
199 return EFI_SUCCESS;\r
200}\r
201\r
202/**\r
203 Do some convertion for the ComponentName2 supported language. It do\r
204 the convertion just for english language code currently.\r
205\r
206 @param ComponentName Pointer to the ComponentName2 protocl pointer.\r
207 @param Language The language string.\r
208\r
209 @return Return the duplication of Language if it is not english otherwise return\r
210 the supported english language code.\r
211\r
212**/\r
213CHAR8 *\r
214ConvertComponentName2SupportLanguage (\r
215 IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName,\r
216 IN CHAR8 *Language\r
217 )\r
218{\r
219 CHAR8 *SupportedLanguages;\r
220 CHAR8 *LangCode;\r
221 UINTN Index;\r
222\r
223 LangCode = NULL;\r
224 SupportedLanguages = NULL;\r
225\r
226 //\r
227 // treat all the english language code (en-xx or eng) equally\r
228 //\r
229 if ((AsciiStrnCmp (Language, "en-", 3) == 0) || (AsciiStrCmp (Language, "eng") == 0)) {\r
230 SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "en");\r
231 if (SupportedLanguages == NULL) {\r
232 SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "eng");\r
233 }\r
234 }\r
235\r
236 //\r
237 // duplicate the Language if it is not english\r
238 //\r
239 if (SupportedLanguages == NULL) {\r
240 SupportedLanguages = Language;\r
241 }\r
242\r
243 //\r
244 // duplicate the returned language code.\r
245 //\r
246 if (AsciiStrStr (SupportedLanguages, "-") != NULL) {\r
247 LangCode = AllocateZeroPool(32);\r
248 for(Index = 0; (Index < 31) && (SupportedLanguages[Index] != '\0') && (SupportedLanguages[Index] != ';'); Index++) {\r
249 LangCode[Index] = SupportedLanguages[Index];\r
250 }\r
251 LangCode[Index] = '\0';\r
252 } else {\r
253 LangCode = AllocateZeroPool(4);\r
254 for(Index = 0; (Index < 3) && (SupportedLanguages[Index] != '\0'); Index++) {\r
255 LangCode[Index] = SupportedLanguages[Index];\r
256 }\r
257 LangCode[Index] = '\0';\r
258 }\r
259 return LangCode;\r
260}\r
261\r
262/**\r
263 Get the ComponentName or ComponentName2 protocol according to the driver binding handle\r
264\r
265 @param DriverBindingHandle The Handle of DriverBinding.\r
266\r
267 @retval !NULL Pointer into the image name if the image name is found,\r
268 @retval NULL Pointer to NULL if the image name is not found.\r
269\r
270**/\r
271CHAR16 *\r
272GetComponentName (\r
273 IN EFI_HANDLE DriverBindingHandle\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
278 EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
279 CHAR8 *SupportedLanguage;\r
280 CHAR16 *DriverName;\r
281\r
282 ComponentName = NULL;\r
283 ComponentName2 = NULL;\r
284 Status = gBS->OpenProtocol (\r
285 DriverBindingHandle,\r
286 &gEfiComponentName2ProtocolGuid,\r
287 (VOID **) &ComponentName2,\r
288 NULL,\r
289 NULL,\r
290 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
291 );\r
292 if (EFI_ERROR(Status)) {\r
293 Status = gBS->OpenProtocol (\r
294 DriverBindingHandle,\r
295 &gEfiComponentNameProtocolGuid,\r
296 (VOID **) &ComponentName,\r
297 NULL,\r
298 NULL,\r
299 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
300 );\r
301 }\r
302\r
303 Status = EFI_SUCCESS;\r
304 DriverName = NULL;\r
305 if (ComponentName != NULL) {\r
306 if (ComponentName->GetDriverName != NULL) {\r
307 Status = ComponentName->GetDriverName (\r
308 ComponentName,\r
309 mLanguage,\r
310 &DriverName\r
311 );\r
312 }\r
313 } else if (ComponentName2 != NULL) {\r
314 if (ComponentName2->GetDriverName != NULL) {\r
315 SupportedLanguage = ConvertComponentName2SupportLanguage (ComponentName2, mLanguage);\r
316 Status = ComponentName2->GetDriverName (\r
317 ComponentName2,\r
318 SupportedLanguage,\r
319 &DriverName\r
320 );\r
321 gBS->FreePool (SupportedLanguage);\r
322 }\r
323 }\r
324 if (EFI_ERROR (Status)) {\r
325 return NULL;\r
326 }\r
327\r
328 return DriverName;\r
329}\r
330\r
331/**\r
332 Get the image name\r
333\r
334 @param Image Image to search.\r
335\r
336 @retval !NULL Pointer into the image name if the image name is found,\r
337 @retval NULL Pointer to NULL if the image name is not found.\r
338\r
339**/\r
340CHAR16 *\r
341GetImageName (\r
342 EFI_LOADED_IMAGE_PROTOCOL *Image\r
343 )\r
344{\r
345 EFI_STATUS Status;\r
346 EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
347 EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
348 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
349 VOID *Buffer;\r
350 UINTN BufferSize;\r
351 UINT32 AuthenticationStatus;\r
352 EFI_GUID *NameGuid;\r
353 EFI_FIRMWARE_VOLUME2_PROTOCOL *FV2;\r
354\r
355 FV2 = NULL;\r
356 Buffer = NULL;\r
357 BufferSize = 0;\r
358\r
359 if (Image->FilePath == NULL) {\r
360 return NULL;\r
361 }\r
362\r
363 DevPath = UnpackDevicePath (Image->FilePath);\r
364\r
365 if (DevPath == NULL) {\r
366 return NULL;\r
367 }\r
368\r
369 DevPathNode = DevPath;\r
370\r
371 while (!IsDevicePathEnd (DevPathNode)) {\r
372 //\r
373 // Find the Fv File path\r
374 //\r
375 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);\r
376 if (NameGuid != NULL) {\r
377 FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevPathNode;\r
378 Status = gBS->HandleProtocol (\r
379 Image->DeviceHandle,\r
380 &gEfiFirmwareVolume2ProtocolGuid,\r
381 (VOID **) &FV2\r
382 );\r
383 if (!EFI_ERROR (Status)) {\r
384 Status = FV2->ReadSection (\r
385 FV2,\r
386 &FvFilePath->FvFileName,\r
387 EFI_SECTION_USER_INTERFACE,\r
388 0,\r
389 &Buffer,\r
390 &BufferSize,\r
391 &AuthenticationStatus\r
392 );\r
393 if (!EFI_ERROR (Status)) {\r
394 break;\r
395 }\r
396 Buffer = NULL;\r
397 }\r
398 }\r
399 //\r
400 // Next device path node\r
401 //\r
402 DevPathNode = NextDevicePathNode (DevPathNode);\r
403 }\r
404\r
405 gBS->FreePool (DevPath);\r
406 return Buffer;\r
407}\r
408\r
409/**\r
410 Prepare the first page to let user select the device controller which need to\r
411 add mapping drivers.\r
412\r
413 @param Private Pointer to EFI_CALLBACK_INFO.\r
414 @param KeyValue The callback key value of device controller item in first page.\r
415 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
416\r
417 @retval EFI_SUCCESS Always returned.\r
418\r
419**/\r
420EFI_STATUS\r
421UpdateDeviceSelectPage (\r
422 IN EFI_CALLBACK_INFO *Private,\r
423 IN UINT16 KeyValue,\r
424 IN PLAT_OVER_MNGR_DATA *FakeNvData\r
425 )\r
426{\r
427 EFI_HII_UPDATE_DATA UpdateData;\r
428 EFI_STATUS Status;\r
429 UINTN LangSize;\r
430 UINTN Index;\r
431 UINTN DevicePathHandleCount;\r
432 CHAR16 *NewString;\r
433 EFI_STRING_ID NewStringToken;\r
434 CHAR16 *ControllerName;\r
435 EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;\r
436 EFI_PCI_IO_PROTOCOL *PciIo;\r
437 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
438 UINTN Len;\r
439\r
440 mCurrentPage = FORM_ID_DEVICE;\r
441 //\r
442 // Following code will be run if user select 'Refresh' in first page\r
443 // During first page, user will see all currnet controller device path in system,\r
444 // select any device path will go to second page to select its overrides drivers\r
445 //\r
446\r
447 LangSize = RFC_3066_ENTRY_SIZE;\r
448 Status = gRT->GetVariable (\r
449 L"PlatformLang",\r
450 &gEfiGlobalVariableGuid,\r
451 NULL,\r
452 &LangSize,\r
453 mLanguage\r
454 );\r
455 ASSERT_EFI_ERROR (Status);\r
456\r
457 //\r
458 // Initial the mapping database in memory\r
459 //\r
460 FreeMappingDatabase (&mMappingDataBase);\r
461 Status = InitOverridesMapping (&mMappingDataBase);\r
462\r
463 //\r
464 // Clear all the content in the first page\r
465 //\r
466 UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
467 UpdateData.Offset = 0;\r
468 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
469 ASSERT (UpdateData.Data != NULL);\r
470 //\r
471 // Clear first page form\r
472 //\r
473 IfrLibUpdateForm (\r
474 Private->RegisteredHandle,\r
475 &mPlatformOverridesManagerGuid,\r
476 FORM_ID_DEVICE,\r
477 FORM_ID_DEVICE,\r
478 FALSE,\r
479 &UpdateData\r
480 );\r
481\r
482 //\r
483 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,\r
484 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement\r
485 //\r
486 NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH);\r
487 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), &NewString);\r
488 ASSERT (NewString != NULL);\r
489 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
490 ASSERT_EFI_ERROR (Status);\r
491 gBS->FreePool (NewString);\r
492\r
493 NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);\r
494 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), &NewString);\r
495 ASSERT (NewString != NULL);\r
496 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
497 ASSERT_EFI_ERROR (Status);\r
498 gBS->FreePool (NewString);\r
499 //\r
500 // created needed controller device item in first page\r
501 //\r
502 DevicePathHandleCount = 0;\r
503 Status = gBS->LocateHandleBuffer (\r
504 ByProtocol,\r
505 &gEfiDevicePathProtocolGuid,\r
506 NULL,\r
507 &DevicePathHandleCount,\r
508 &mDevicePathHandleBuffer\r
509 );\r
510 if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {\r
511 return EFI_SUCCESS;\r
512 }\r
513\r
514 for (Index = 0; Index < DevicePathHandleCount; Index++) {\r
515 if (FakeNvData->PciDeviceFilter == 0x01) {\r
516 //\r
517 // Only care PCI device which contain efi driver in its option rom.\r
518 //\r
519\r
520 //\r
521 // Check whether it is a pci device\r
522 //\r
523 ControllerDevicePath = NULL;\r
524 Status = gBS->OpenProtocol (\r
525 mDevicePathHandleBuffer[Index],\r
526 &gEfiPciIoProtocolGuid,\r
527 (VOID **) &PciIo,\r
528 NULL,\r
529 NULL,\r
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
531 );\r
532 if (EFI_ERROR (Status)) {\r
533 continue;\r
534 }\r
535 //\r
536 // Check whether it contain efi driver in its option rom\r
537 //\r
538 Status = gBS->HandleProtocol(\r
539 mDevicePathHandleBuffer[Index],\r
540 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
541 (VOID **) &BusSpecificDriverOverride\r
542 );\r
543 if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
544 continue;\r
545 }\r
546 }\r
547\r
548 ControllerDevicePath = NULL;\r
549 Status = gBS->OpenProtocol (\r
550 mDevicePathHandleBuffer[Index],\r
551 &gEfiDevicePathProtocolGuid,\r
552 (VOID **) &ControllerDevicePath,\r
553 NULL,\r
554 NULL,\r
555 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
556 );\r
557 ASSERT_EFI_ERROR (Status);\r
558 //\r
559 // Save the device path protocol interface\r
560 //\r
561 mControllerDevicePathProtocol[Index] = ControllerDevicePath;\r
562\r
563 //\r
564 // Get the driver name\r
565 //\r
566 ControllerName = DevicePathToStr (ControllerDevicePath);\r
567\r
568 //\r
569 // Export the driver name string and create item in set options page\r
570 //\r
571 Len = StrSize (ControllerName);\r
572 NewString = AllocateZeroPool (Len + StrSize (L"--"));\r
573 if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {\r
574 StrCat (NewString, L"--");\r
575 } else {\r
576 StrCat (NewString, L"**");\r
577 }\r
578 StrCat (NewString, ControllerName);\r
579\r
580 NewStringToken = mControllerToken[Index];\r
581 if (NewStringToken == 0) {\r
582 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);\r
583 } else {\r
584 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
585 }\r
586 ASSERT_EFI_ERROR (Status);\r
587 gBS->FreePool (NewString);\r
588 //\r
589 // Save the device path string toke for next access use\r
590 //\r
591 mControllerToken[Index] = NewStringToken;\r
592\r
593 CreateGotoOpCode (\r
594 FORM_ID_DRIVER,\r
595 NewStringToken,\r
596 STRING_TOKEN (STR_GOTO_HELP_DRIVER),\r
597 EFI_IFR_FLAG_CALLBACK,\r
598 (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET),\r
599 &UpdateData\r
600 );\r
601 }\r
602\r
603 //\r
604 // Update first page form\r
605 //\r
606 IfrLibUpdateForm (\r
607 Private->RegisteredHandle,\r
608 &mPlatformOverridesManagerGuid,\r
609 FORM_ID_DEVICE,\r
610 FORM_ID_DEVICE,\r
611 FALSE,\r
612 &UpdateData\r
613 );\r
614\r
615 gBS->FreePool (UpdateData.Data);\r
616 return EFI_SUCCESS;\r
617}\r
618\r
619/**\r
620 Prepare to let user select the drivers which need mapping with the device controller\r
621 selected in first page.\r
622\r
623 @param Private Pointer to EFI_CALLBACK_INFO.\r
624 @param KeyValue The callback key value of device controller item in first page.\r
625 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
626\r
627 @retval EFI_SUCCESS Always returned.\r
628\r
629**/\r
630EFI_STATUS\r
631UpdateBindingDriverSelectPage (\r
632 IN EFI_CALLBACK_INFO *Private,\r
633 IN UINT16 KeyValue,\r
634 IN PLAT_OVER_MNGR_DATA *FakeNvData\r
635 )\r
636{\r
637 EFI_HII_UPDATE_DATA UpdateData;\r
638 EFI_STATUS Status;\r
639 UINTN Index;\r
640\r
641 CHAR16 *NewString;\r
642 EFI_STRING_ID NewStringToken;\r
643 EFI_STRING_ID NewStringHelpToken;\r
644 UINTN DriverImageHandleCount;\r
645\r
646 EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;\r
647 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
648 CHAR16 *DriverName;\r
649 BOOLEAN FreeDriverName;\r
650\r
651 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
652 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
653 EFI_HANDLE DriverBindingHandle;\r
654 //\r
655 // If user select a controller item in the first page the following code will be run.\r
656 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown\r
657 //\r
658 //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols\r
659 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.\r
660 // then use the Component Name Protocol on the same handle as the first matching Driver Binding Protocol to look up the name of the driver.\r
661 //\r
662\r
663 mCurrentPage = FORM_ID_DRIVER;\r
664 //\r
665 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer\r
666 //\r
667 mSelectedCtrIndex = KeyValue - 0x100;\r
668 ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);\r
669 mLastSavedDriverImageNum = 0;\r
670 //\r
671 // Clear all the content in dynamic page\r
672 //\r
673 UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
674 UpdateData.Offset = 0;\r
675 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
676 ASSERT (UpdateData.Data != NULL);\r
677 //\r
678 // Clear second page form\r
679 //\r
680 IfrLibUpdateForm (\r
681 Private->RegisteredHandle,\r
682 &mPlatformOverridesManagerGuid,\r
683 FORM_ID_DRIVER,\r
684 FORM_ID_DRIVER,\r
685 FALSE,\r
686 &UpdateData\r
687 );\r
688\r
689 //\r
690 // Show all driver which support loaded image protocol in second page\r
691 //\r
692 DriverImageHandleCount = 0;\r
693 Status = gBS->LocateHandleBuffer (\r
694 ByProtocol,\r
695 &gEfiLoadedImageProtocolGuid,\r
696 NULL,\r
697 &DriverImageHandleCount,\r
698 &mDriverImageHandleBuffer\r
699 );\r
700 if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {\r
701 return EFI_NOT_FOUND;\r
702 }\r
703\r
704 mDriverImageHandleCount = DriverImageHandleCount;\r
705 for (Index = 0; Index < DriverImageHandleCount; Index++) {\r
706 //\r
707 // Step1: Get the driver image total file path for help string and the driver name.\r
708 //\r
709\r
710 //\r
711 // Find driver's Loaded Image protocol\r
712 //\r
713 LoadedImage =NULL;\r
714\r
715 Status = gBS->OpenProtocol (\r
716 mDriverImageHandleBuffer[Index],\r
717 &gEfiLoadedImageProtocolGuid,\r
718 (VOID **) &LoadedImage,\r
719 NULL,\r
720 NULL,\r
721 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
722 );\r
723 if (EFI_ERROR (Status)) {\r
724 FakeNvData->DriSelection[Index] = 0x00;\r
725 continue;\r
726 }\r
727 mDriverImageProtocol[Index] = LoadedImage;\r
728 //\r
729 // Find its related driver binding protocol\r
730 //\r
731 DriverBindingInterface = NULL;\r
732 DriverBindingHandle = NULL;\r
733 DriverBindingInterface = GetBindingProtocolFromImageHandle (\r
734 mDriverImageHandleBuffer[Index],\r
735 &DriverBindingHandle\r
736 );\r
737 if (DriverBindingInterface == NULL) {\r
738 FakeNvData->DriSelection[Index] = 0x00;\r
739 continue;\r
740 }\r
741\r
742 //\r
743 // Get the EFI Loaded Image Device Path Protocol\r
744 //\r
745 LoadedImageDevicePath = NULL;\r
746 Status = gBS->HandleProtocol (\r
747 mDriverImageHandleBuffer[Index],\r
748 &gEfiLoadedImageDevicePathProtocolGuid,\r
749 (VOID **) &LoadedImageDevicePath\r
750 );\r
751 if (LoadedImageDevicePath == NULL) {\r
752 FakeNvData->DriSelection[Index] = 0x00;\r
753 continue;\r
754 }\r
755\r
756 if (FakeNvData->PciDeviceFilter == 0x01) {\r
757 //\r
758 // only care the driver which is in a Pci device option rom,\r
759 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom\r
760 //\r
761 if (!EFI_ERROR (Status)) {\r
762 Status = gBS->HandleProtocol(\r
763 LoadedImage->DeviceHandle,\r
764 &gEfiBusSpecificDriverOverrideProtocolGuid,\r
765 (VOID **) &BusSpecificDriverOverride\r
766 );\r
767 if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
768 FakeNvData->DriSelection[Index] = 0x00;\r
769 continue;\r
770 }\r
771 } else {\r
772 FakeNvData->DriSelection[Index] = 0x00;\r
773 continue;\r
774 }\r
775 }\r
776\r
777 //\r
778 // For driver name, try to get its component name, if fail, get its image name,\r
779 // if also fail, give a default name.\r
780 //\r
781 FreeDriverName = FALSE;\r
782 DriverName = GetComponentName (DriverBindingHandle);\r
783 if (DriverName == NULL) {\r
784 //\r
785 // get its image name\r
786 //\r
787 DriverName = GetImageName (LoadedImage);\r
788 }\r
789 if (DriverName == NULL) {\r
790 //\r
791 // give a default name\r
792 //\r
793 HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), &DriverName);\r
794 ASSERT (DriverName != NULL);\r
795 FreeDriverName = TRUE; // the DriverName string need to free pool\r
796 }\r
797\r
798\r
799 //\r
800 // Step2 Export the driver name string and create check box item in second page\r
801 //\r
802\r
803 //\r
804 // First create the driver image name\r
805 //\r
806 NewString = AllocateZeroPool (StrSize (DriverName));\r
807 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {\r
808 FakeNvData->DriSelection[Index] = 0x00;\r
809 } else {\r
810 FakeNvData->DriSelection[Index] = 0x01;\r
811 mLastSavedDriverImageNum++;\r
812 }\r
813 StrCat (NewString, DriverName);\r
814 NewStringToken = mDriverImageToken[Index];\r
815 if (NewStringToken == 0) {\r
816 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);\r
817 } else {\r
818 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
819 }\r
820 mDriverImageToken[Index] = NewStringToken;\r
821 ASSERT_EFI_ERROR (Status);\r
822 gBS->FreePool (NewString);\r
823 if (FreeDriverName) {\r
824 gBS->FreePool (DriverName);\r
825 }\r
826\r
827 //\r
828 // Second create the driver image device path as item help string\r
829 //\r
830 DriverName = DevicePathToStr (LoadedImageDevicePath);\r
831\r
832 NewString = AllocateZeroPool (StrSize (DriverName));\r
833 StrCat (NewString, DriverName);\r
834 NewStringHelpToken = mDriverImageFilePathToken[Index];\r
835 if (NewStringHelpToken == 0) {\r
836 Status = HiiLibNewString (Private->RegisteredHandle, &NewStringHelpToken, NewString);\r
837 } else {\r
838 Status = HiiLibSetString (Private->RegisteredHandle, NewStringHelpToken, NewString);\r
839 }\r
840 mDriverImageFilePathToken[Index] = NewStringHelpToken;\r
841 ASSERT_EFI_ERROR (Status);\r
842 gBS->FreePool (NewString);\r
843 gBS->FreePool (DriverName);\r
844\r
845 CreateCheckBoxOpCode (\r
846 (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),\r
847 VARSTORE_ID_PLAT_OVER_MNGR,\r
848 (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),\r
849 NewStringToken,\r
850 NewStringHelpToken,\r
851 0,\r
852 0,\r
853 &UpdateData\r
854 );\r
855 }\r
856\r
857 //\r
858 // Update second page form\r
859 //\r
860 IfrLibUpdateForm (\r
861 Private->RegisteredHandle,\r
862 &mPlatformOverridesManagerGuid,\r
863 FORM_ID_DRIVER,\r
864 FORM_ID_DRIVER,\r
865 FALSE,\r
866 &UpdateData\r
867 );\r
868\r
869 gBS->FreePool (UpdateData.Data);\r
870 return EFI_SUCCESS;\r
871}\r
872\r
873/**\r
874 Prepare to let user select the priority order of the drivers which are\r
875 selected in second page.\r
876\r
877 @param Private Pointer to EFI_CALLBACK_INFO.\r
878 @param KeyValue The callback key value of device controller item in first page.\r
879 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
880\r
881 @retval EFI_SUCCESS Always returned.\r
882\r
883**/\r
884EFI_STATUS\r
885UpdatePrioritySelectPage (\r
886 IN EFI_CALLBACK_INFO *Private,\r
887 IN UINT16 KeyValue,\r
888 IN PLAT_OVER_MNGR_DATA *FakeNvData\r
889 )\r
890{\r
891 EFI_HII_UPDATE_DATA UpdateData;\r
892 UINTN Index;\r
893\r
894 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
895\r
896 IFR_OPTION *IfrOptionList;\r
897 UINTN SelectedDriverImageNum;\r
898 UINT32 DriverImageNO;\r
899 UINTN MinNO;\r
900 UINTN Index1;\r
901 UINTN TempNO[100];\r
902\r
903 //\r
904 // Following code will be run if user select 'order ... priority' item in second page\r
905 // Prepare third page. In third page, user will order the drivers priority which are selected in second page\r
906 //\r
907 mCurrentPage = FORM_ID_ORDER;\r
908\r
909 UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
910 UpdateData.Offset = 0;\r
911 UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
912 ASSERT (UpdateData.Data != NULL);\r
913 //\r
914 // Clear third page form\r
915 //\r
916 IfrLibUpdateForm (\r
917 Private->RegisteredHandle,\r
918 &mPlatformOverridesManagerGuid,\r
919 FORM_ID_ORDER,\r
920 FORM_ID_ORDER,\r
921 FALSE,\r
922 &UpdateData\r
923 );\r
924\r
925 //\r
926 // Check how many drivers have been selected\r
927 //\r
928 SelectedDriverImageNum = 0;\r
929 for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
930 if (FakeNvData->DriSelection[Index] != 0) {\r
931 SelectedDriverImageNum ++;\r
932 }\r
933 }\r
934\r
935 mSelectedDriverImageNum = SelectedDriverImageNum;\r
936 if (SelectedDriverImageNum == 0) {\r
937 return EFI_SUCCESS;\r
938 }\r
939\r
940 IfrOptionList = AllocateZeroPool (0x200);\r
941 ASSERT_EFI_ERROR (IfrOptionList != NULL);\r
942 //\r
943 // Create order list for those selected drivers\r
944 //\r
945 SelectedDriverImageNum = 0;\r
946 for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
947 if (FakeNvData->DriSelection[Index] != 0) {\r
948 IfrOptionList[SelectedDriverImageNum].StringToken = mDriverImageToken[Index];\r
949 //\r
950 // Use the NO. in driver binding buffer as value, will use it later\r
951 //\r
952 IfrOptionList[SelectedDriverImageNum].Value.u8 = (UINT8) (Index + 1);\r
953 IfrOptionList[SelectedDriverImageNum].Flags = 0;\r
954\r
955 //\r
956 // Get the EFI Loaded Image Device Path Protocol\r
957 //\r
958 LoadedImageDevicePath = NULL;\r
959 gBS->HandleProtocol (\r
960 mDriverImageHandleBuffer[Index],\r
961 &gEfiLoadedImageDevicePathProtocolGuid,\r
962 (VOID **) &LoadedImageDevicePath\r
963 );\r
964 ASSERT (LoadedImageDevicePath != NULL);\r
965\r
966 //\r
967 // Check the driver DriverImage's order number in mapping database\r
968 //\r
969 DriverImageNO = 0;\r
970 CheckMapping (\r
971 mControllerDevicePathProtocol[mSelectedCtrIndex],\r
972 LoadedImageDevicePath,\r
973 &mMappingDataBase,\r
974 NULL,\r
975 &DriverImageNO\r
976 );\r
977 if (DriverImageNO == 0) {\r
978 DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1;\r
979 mLastSavedDriverImageNum++;\r
980 }\r
981 TempNO[SelectedDriverImageNum] = DriverImageNO;\r
982 SelectedDriverImageNum ++;\r
983 }\r
984 }\r
985\r
986 ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);\r
987 //\r
988 // NvRamMap Must be clear firstly\r
989 //\r
990 ZeroMem (FakeNvData->DriOrder, 100);\r
991\r
992 //\r
993 // Order the selected drivers according to the info already in mapping database\r
994 // the less order number in mapping database the less order number in NvRamMap\r
995 //\r
996 for (Index=0; Index < SelectedDriverImageNum; Index++) {\r
997 //\r
998 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array\r
999 //\r
1000 MinNO = 0;\r
1001 for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) {\r
1002 if (TempNO[Index1] < TempNO[MinNO]) {\r
1003 MinNO = Index1;\r
1004 }\r
1005 }\r
1006 //\r
1007 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer\r
1008 //\r
1009 FakeNvData->DriOrder[Index] =IfrOptionList[MinNO].Value.u8;\r
1010 TempNO[MinNO] = 101;\r
1011 }\r
1012\r
1013 CreateOrderedListOpCode (\r
1014 (UINT16) DRIVER_ORDER_QUESTION_ID,\r
1015 VARSTORE_ID_PLAT_OVER_MNGR,\r
1016 (UINT16) DRIVER_ORDER_VAR_OFFSET,\r
1017 mControllerToken[mSelectedCtrIndex],\r
1018 mControllerToken[mSelectedCtrIndex],\r
1019 EFI_IFR_FLAG_RESET_REQUIRED,\r
1020 0,\r
1021 EFI_IFR_NUMERIC_SIZE_1,\r
1022 100,\r
1023 IfrOptionList,\r
1024 SelectedDriverImageNum,\r
1025 &UpdateData\r
1026 );\r
1027\r
1028 //\r
1029 // Update third page form\r
1030 //\r
1031 IfrLibUpdateForm (\r
1032 Private->RegisteredHandle,\r
1033 &mPlatformOverridesManagerGuid,\r
1034 FORM_ID_ORDER,\r
1035 FORM_ID_ORDER,\r
1036 FALSE,\r
1037 &UpdateData\r
1038 );\r
1039\r
1040 gBS->FreePool (IfrOptionList);\r
1041 gBS->FreePool (UpdateData.Data);\r
1042 return EFI_SUCCESS;\r
1043}\r
1044\r
1045/**\r
1046 Save the save the mapping database to NV variable.\r
1047\r
1048 @param Private Pointer to EFI_CALLBACK_INFO.\r
1049 @param KeyValue The callback key value of device controller item in first page.\r
1050 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
1051\r
1052 @retval EFI_SUCCESS Always returned.\r
1053\r
1054**/\r
1055EFI_STATUS\r
1056CommintChanges (\r
1057 IN EFI_CALLBACK_INFO *Private,\r
1058 IN UINT16 KeyValue,\r
1059 IN PLAT_OVER_MNGR_DATA *FakeNvData\r
1060 )\r
1061{\r
1062 EFI_STATUS Status;\r
1063 UINTN Index;\r
1064 UINTN SelectedDriverImageNum;\r
1065 EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
1066 //\r
1067 // Following code will be run if user select 'commint changes' in third page\r
1068 // user enter 'Commit Changes' to save the mapping database\r
1069 //\r
1070 DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase);\r
1071 for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) {\r
1072 //\r
1073 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer\r
1074 //\r
1075 Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1;\r
1076\r
1077 //\r
1078 // Get the EFI Loaded Image Device Path Protocol\r
1079 //\r
1080 LoadedImageDevicePath = NULL;\r
1081 Status = gBS->HandleProtocol (\r
1082 mDriverImageHandleBuffer[Index],\r
1083 &gEfiLoadedImageDevicePathProtocolGuid,\r
1084 (VOID **) &LoadedImageDevicePath\r
1085 );\r
1086 ASSERT (LoadedImageDevicePath != NULL);\r
1087\r
1088 InsertDriverImage (\r
1089 mControllerDevicePathProtocol[mSelectedCtrIndex],\r
1090 LoadedImageDevicePath,\r
1091 &mMappingDataBase,\r
1092 (UINT32)SelectedDriverImageNum + 1\r
1093 );\r
1094 }\r
1095 Status = SaveOverridesMapping (&mMappingDataBase);\r
1096\r
1097 return Status;\r
1098}\r
1099\r
1100/**\r
1101 This function allows a caller to extract the current configuration for one\r
1102 or more named elements from the target driver.\r
1103\r
1104 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1105 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
1106 @param Progress On return, points to a character in the Request string.\r
1107 Points to the string's null terminator if request was successful.\r
1108 Points to the most recent '&' before the first failing name/value\r
1109 pair (or the beginning of the string if the failure is in the\r
1110 first name/value pair) if the request was not successful.\r
1111 @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
1112 has all values filled in for the names in the Request string.\r
1113 String to be allocated by the called function.\r
1114\r
1115 @retval EFI_SUCCESS The Results is filled with the requested values.\r
1116 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
1117 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
1118 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
1119\r
1120**/\r
1121EFI_STATUS\r
1122EFIAPI\r
1123PlatOverMngrExtractConfig (\r
1124 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1125 IN CONST EFI_STRING Request,\r
1126 OUT EFI_STRING *Progress,\r
1127 OUT EFI_STRING *Results\r
1128 )\r
1129{\r
1130 EFI_STATUS Status;\r
1131 EFI_CALLBACK_INFO *Private;\r
1132 EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
1133\r
1134 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1135 HiiConfigRouting = Private->HiiConfigRouting;\r
1136\r
1137 //\r
1138 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1139 //\r
1140 Status = HiiConfigRouting->BlockToConfig (\r
1141 HiiConfigRouting,\r
1142 Request,\r
1143 (UINT8 *) &Private->FakeNvData,\r
1144 sizeof (PLAT_OVER_MNGR_DATA),\r
1145 Results,\r
1146 Progress\r
1147 );\r
1148 return Status;\r
1149}\r
1150\r
1151/**\r
1152 This function processes the results of changes in configuration.\r
1153\r
1154 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1155 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
1156 @param Progress A pointer to a string filled in with the offset of the most\r
1157 recent '&' before the first failing name/value pair (or the\r
1158 beginning of the string if the failure is in the first\r
1159 name/value pair) or the terminating NULL if all was successful.\r
1160\r
1161 @retval EFI_SUCCESS The Results is processed successfully.\r
1162 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
1163 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
1164\r
1165**/\r
1166EFI_STATUS\r
1167EFIAPI\r
1168PlatOverMngrRouteConfig (\r
1169 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1170 IN CONST EFI_STRING Configuration,\r
1171 OUT EFI_STRING *Progress\r
1172 )\r
1173{\r
1174 EFI_CALLBACK_INFO *Private;\r
1175 EFI_STATUS Status;\r
1176 UINT16 KeyValue;\r
1177 UINTN BufferSize;\r
1178 PLAT_OVER_MNGR_DATA *FakeNvData;\r
1179\r
1180 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1181\r
1182 FakeNvData = &Private->FakeNvData;\r
1183 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1184 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
1185 if (EFI_ERROR (Status)) {\r
1186 return Status;\r
1187 }\r
1188\r
1189 if (mCurrentPage == FORM_ID_DRIVER) {\r
1190 KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;\r
1191 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1192 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1193 CommintChanges (Private, KeyValue, FakeNvData);\r
1194 //\r
1195 // Since UpdatePrioritySelectPage will change mCurrentPage,\r
1196 // should ensure the mCurrentPage still indicate the second page here\r
1197 //\r
1198 mCurrentPage = FORM_ID_DRIVER;\r
1199 }\r
1200\r
1201 if (mCurrentPage == FORM_ID_ORDER) {\r
1202 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1203 CommintChanges (Private, KeyValue, FakeNvData);\r
1204 }\r
1205 return EFI_SUCCESS;\r
1206}\r
1207\r
1208/**\r
1209 This is the function that is called to provide results data to the driver. This data\r
1210 consists of a unique key which is used to identify what data is either being passed back\r
1211 or being asked for.\r
1212\r
1213 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1214 @param Action A null-terminated Unicode string in <ConfigRequest> format.\r
1215 @param KeyValue A unique Goto OpCode callback value which record user's selection.\r
1216 0x100 <= KeyValue <0x500 : user select a controller item in the first page;\r
1217 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page\r
1218 KeyValue == 0x1235 : user select 'Pci device filter' in first page\r
1219 KeyValue == 0x1500 : user select 'order ... priority' item in second page\r
1220 KeyValue == 0x1800 : user select 'commint changes' in third page\r
1221 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page\r
1222 @param Type The type of value for the question.\r
1223 @param Value A pointer to the data being sent to the original exporting driver.\r
1224 @param ActionRequest On return, points to the action requested by the callback function.\r
1225\r
1226 @retval EFI_SUCCESS Always returned.\r
1227\r
1228**/\r
1229EFI_STATUS\r
1230EFIAPI\r
1231PlatOverMngrCallback (\r
1232 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1233 IN EFI_BROWSER_ACTION Action,\r
1234 IN EFI_QUESTION_ID KeyValue,\r
1235 IN UINT8 Type,\r
1236 IN EFI_IFR_TYPE_VALUE *Value,\r
1237 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1238 )\r
1239{\r
1240 EFI_CALLBACK_INFO *Private;\r
1241 EFI_STATUS Status;\r
1242 EFI_STRING_ID NewStringToken;\r
1243 UINTN BufferSize;\r
1244 PLAT_OVER_MNGR_DATA *FakeNvData;\r
1245 EFI_INPUT_KEY Key;\r
1246\r
1247 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1248\r
1249 FakeNvData = &Private->FakeNvData;\r
1250 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1251 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
1252 if (EFI_ERROR (Status)) {\r
1253 return Status;\r
1254 }\r
1255\r
1256 if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||\r
1257 KeyValue == KEY_VALUE_DEVICE_FILTER ||\r
1258 KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS\r
1259 ) {\r
1260 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1261 //\r
1262 // Update page title string\r
1263 //\r
1264 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1265 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path");\r
1266 ASSERT_EFI_ERROR (Status);\r
1267 }\r
1268\r
1269 if (((KEY_VALUE_DEVICE_OFFSET <= KeyValue) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {\r
1270 if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {\r
1271 KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + 0x100);\r
1272 }\r
1273 UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);\r
1274 //\r
1275 // Update page title string\r
1276 //\r
1277 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1278 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller");\r
1279 ASSERT_EFI_ERROR (Status);\r
1280 }\r
1281\r
1282 if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {\r
1283 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1284 //\r
1285 // Update page title string\r
1286 //\r
1287 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1288 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them");\r
1289 ASSERT_EFI_ERROR (Status);\r
1290 }\r
1291\r
1292 if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {\r
1293 Status = CommintChanges (Private, KeyValue, FakeNvData);\r
1294 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1295 if (EFI_ERROR (Status)) {\r
1296 IfrLibCreatePopUp (1, &Key, L"Single Override Info too large, Saving Error!");\r
1297 return EFI_DEVICE_ERROR;\r
1298 }\r
1299 }\r
1300\r
1301 if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {\r
1302 //\r
1303 // Deletes all environment variable(s) that contain the override mappings info\r
1304 //\r
1305 FreeMappingDatabase (&mMappingDataBase);\r
1306 Status = SaveOverridesMapping (&mMappingDataBase);\r
1307 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1308 }\r
1309 //\r
1310 // Pass changed uncommitted data back to Form Browser\r
1311 //\r
1312 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1313 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) FakeNvData, NULL);\r
1314\r
1315 return EFI_SUCCESS;\r
1316}\r
1317\r
1318/**\r
1319 Function unpacks a device path data structure so that all the nodes\r
1320 of a device path are naturally aligned.\r
1321\r
1322 @param DevPath A pointer to a device path data structure\r
1323\r
1324 @return If the memory for the device path is successfully allocated, then a\r
1325 @return pointer to the new device path is returned. Otherwise, NULL is returned.\r
1326\r
1327**/\r
1328EFI_DEVICE_PATH_PROTOCOL *\r
1329UnpackDevicePath (\r
1330 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
1331 )\r
1332{\r
1333 EFI_DEVICE_PATH_PROTOCOL *Src;\r
1334 EFI_DEVICE_PATH_PROTOCOL *Dest;\r
1335 EFI_DEVICE_PATH_PROTOCOL *NewPath;\r
1336 UINTN Size;\r
1337\r
1338 //\r
1339 // Walk device path and round sizes to valid boundries\r
1340 //\r
1341 Src = DevPath;\r
1342 Size = 0;\r
1343 for (;;) {\r
1344 Size += DevicePathNodeLength (Src);\r
1345 Size += ALIGN_SIZE (Size);\r
1346\r
1347 if (IsDevicePathEnd (Src)) {\r
1348 break;\r
1349 }\r
1350\r
1351 Src = NextDevicePathNode (Src);\r
1352 }\r
1353 //\r
1354 // Allocate space for the unpacked path\r
1355 //\r
1356 NewPath = AllocateZeroPool (Size);\r
1357 if (NewPath) {\r
1358\r
1359 ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
1360\r
1361 //\r
1362 // Copy each node\r
1363 //\r
1364 Src = DevPath;\r
1365 Dest = NewPath;\r
1366 for (;;) {\r
1367 Size = DevicePathNodeLength (Src);\r
1368 CopyMem (Dest, Src, Size);\r
1369 Size += ALIGN_SIZE (Size);\r
1370 SetDevicePathNodeLength (Dest, Size);\r
1371 Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
1372 Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
1373\r
1374 if (IsDevicePathEnd (Src)) {\r
1375 break;\r
1376 }\r
1377\r
1378 Src = NextDevicePathNode (Src);\r
1379 }\r
1380 }\r
1381\r
1382 return NewPath;\r
1383}\r
1384\r
1385\r
1386/**\r
1387 Get the description string by device path.\r
1388\r
1389 @param DevPath The input device path.\r
1390\r
1391 @retval !NULL The description string retured.\r
1392 @retval NULL The description string cannot be found.\r
1393\r
1394**/\r
1395CHAR16 *\r
1396DevicePathToStr (\r
1397 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
1398 )\r
1399{\r
1400 EFI_STATUS Status;\r
1401 CHAR16 *ToText;\r
1402 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
1403\r
1404 if (DevPath == NULL) {\r
1405 return NULL;\r
1406 }\r
1407\r
1408 Status = gBS->LocateProtocol (\r
1409 &gEfiDevicePathToTextProtocolGuid,\r
1410 NULL,\r
1411 (VOID **) &DevPathToText\r
1412 );\r
1413 if (!EFI_ERROR (Status)) {\r
1414 ToText = DevPathToText->ConvertDevicePathToText (\r
1415 DevPath,\r
1416 FALSE,\r
1417 TRUE\r
1418 );\r
1419 ASSERT (ToText != NULL);\r
1420 return ToText;\r
1421 }\r
1422\r
1423 return NULL;\r
1424}\r