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