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