]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/PlatformDriverOverride/PlatOverMngr/PlatOverMngr.c
1, Move device path utility macros from protocol's header file to DevicePathLib libra...
[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
fe1e36e5 34EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;\r
a6f164a7 35\r
fe1e36e5 36LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);\r
a6f164a7 37\r
fe1e36e5 38EFI_HANDLE *mDevicePathHandleBuffer;\r
39EFI_HANDLE *mDriverImageHandleBuffer;\r
a6f164a7 40\r
fe1e36e5 41UINTN mSelectedCtrIndex;\r
42EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];\r
a6f164a7 43\r
fe1e36e5 44UINTN mDriverImageHandleCount;\r
45EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM];\r
46EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM];\r
47EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM];\r
48EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM];\r
49UINTN mSelectedDriverImageNum;\r
50UINTN mLastSavedDriverImageNum;\r
51CHAR8 mLanguage[RFC_3066_ENTRY_SIZE];\r
52UINT16 mCurrentPage;\r
a6f164a7 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
912004c0
LG
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
a6f164a7 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
8d00a0f1 1131 if (Request == NULL) {\r
1132 return EFI_NOT_FOUND;\r
1133 }\r
1134\r
a6f164a7 1135 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1136 HiiConfigRouting = Private->HiiConfigRouting;\r
1137\r
1138 //\r
1139 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
1140 //\r
1141 Status = HiiConfigRouting->BlockToConfig (\r
1142 HiiConfigRouting,\r
1143 Request,\r
1144 (UINT8 *) &Private->FakeNvData,\r
1145 sizeof (PLAT_OVER_MNGR_DATA),\r
1146 Results,\r
1147 Progress\r
1148 );\r
1149 return Status;\r
1150}\r
1151\r
1152/**\r
1153 This function processes the results of changes in configuration.\r
1154\r
1155 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1156 @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
1157 @param Progress A pointer to a string filled in with the offset of the most\r
1158 recent '&' before the first failing name/value pair (or the\r
1159 beginning of the string if the failure is in the first\r
1160 name/value pair) or the terminating NULL if all was successful.\r
1161\r
1162 @retval EFI_SUCCESS The Results is processed successfully.\r
1163 @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
1164 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
1165\r
1166**/\r
1167EFI_STATUS\r
1168EFIAPI\r
1169PlatOverMngrRouteConfig (\r
1170 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1171 IN CONST EFI_STRING Configuration,\r
1172 OUT EFI_STRING *Progress\r
1173 )\r
1174{\r
1175 EFI_CALLBACK_INFO *Private;\r
1176 EFI_STATUS Status;\r
1177 UINT16 KeyValue;\r
1178 UINTN BufferSize;\r
1179 PLAT_OVER_MNGR_DATA *FakeNvData;\r
1180\r
1181 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1182\r
1183 FakeNvData = &Private->FakeNvData;\r
1184 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1185 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
1186 if (EFI_ERROR (Status)) {\r
1187 return Status;\r
1188 }\r
1189\r
1190 if (mCurrentPage == FORM_ID_DRIVER) {\r
1191 KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;\r
1192 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1193 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1194 CommintChanges (Private, KeyValue, FakeNvData);\r
1195 //\r
1196 // Since UpdatePrioritySelectPage will change mCurrentPage,\r
1197 // should ensure the mCurrentPage still indicate the second page here\r
1198 //\r
1199 mCurrentPage = FORM_ID_DRIVER;\r
1200 }\r
1201\r
1202 if (mCurrentPage == FORM_ID_ORDER) {\r
1203 KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
1204 CommintChanges (Private, KeyValue, FakeNvData);\r
1205 }\r
1206 return EFI_SUCCESS;\r
1207}\r
1208\r
1209/**\r
1210 This is the function that is called to provide results data to the driver. This data\r
1211 consists of a unique key which is used to identify what data is either being passed back\r
1212 or being asked for.\r
1213\r
1214 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
1215 @param Action A null-terminated Unicode string in <ConfigRequest> format.\r
1216 @param KeyValue A unique Goto OpCode callback value which record user's selection.\r
1217 0x100 <= KeyValue <0x500 : user select a controller item in the first page;\r
1218 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page\r
1219 KeyValue == 0x1235 : user select 'Pci device filter' in first page\r
1220 KeyValue == 0x1500 : user select 'order ... priority' item in second page\r
1221 KeyValue == 0x1800 : user select 'commint changes' in third page\r
1222 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page\r
1223 @param Type The type of value for the question.\r
1224 @param Value A pointer to the data being sent to the original exporting driver.\r
1225 @param ActionRequest On return, points to the action requested by the callback function.\r
1226\r
1227 @retval EFI_SUCCESS Always returned.\r
1228\r
1229**/\r
1230EFI_STATUS\r
1231EFIAPI\r
1232PlatOverMngrCallback (\r
1233 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
1234 IN EFI_BROWSER_ACTION Action,\r
1235 IN EFI_QUESTION_ID KeyValue,\r
1236 IN UINT8 Type,\r
1237 IN EFI_IFR_TYPE_VALUE *Value,\r
1238 OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
1239 )\r
1240{\r
1241 EFI_CALLBACK_INFO *Private;\r
1242 EFI_STATUS Status;\r
1243 EFI_STRING_ID NewStringToken;\r
1244 UINTN BufferSize;\r
1245 PLAT_OVER_MNGR_DATA *FakeNvData;\r
1246 EFI_INPUT_KEY Key;\r
1247\r
1248 Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
1249\r
1250 FakeNvData = &Private->FakeNvData;\r
1251 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1252 Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
1253 if (EFI_ERROR (Status)) {\r
1254 return Status;\r
1255 }\r
1256\r
1257 if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||\r
1258 KeyValue == KEY_VALUE_DEVICE_FILTER ||\r
1259 KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS\r
1260 ) {\r
1261 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1262 //\r
1263 // Update page title string\r
1264 //\r
1265 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1266 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path");\r
1267 ASSERT_EFI_ERROR (Status);\r
1268 }\r
1269\r
1270 if (((KEY_VALUE_DEVICE_OFFSET <= KeyValue) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {\r
1271 if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {\r
1272 KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + 0x100);\r
1273 }\r
1274 UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);\r
1275 //\r
1276 // Update page title string\r
1277 //\r
1278 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1279 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller");\r
1280 ASSERT_EFI_ERROR (Status);\r
1281 }\r
1282\r
1283 if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {\r
1284 UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
1285 //\r
1286 // Update page title string\r
1287 //\r
1288 NewStringToken = STRING_TOKEN (STR_TITLE);\r
1289 Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them");\r
1290 ASSERT_EFI_ERROR (Status);\r
1291 }\r
1292\r
1293 if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {\r
1294 Status = CommintChanges (Private, KeyValue, FakeNvData);\r
1295 *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
1296 if (EFI_ERROR (Status)) {\r
1297 IfrLibCreatePopUp (1, &Key, L"Single Override Info too large, Saving Error!");\r
1298 return EFI_DEVICE_ERROR;\r
1299 }\r
1300 }\r
1301\r
1302 if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {\r
1303 //\r
1304 // Deletes all environment variable(s) that contain the override mappings info\r
1305 //\r
1306 FreeMappingDatabase (&mMappingDataBase);\r
1307 Status = SaveOverridesMapping (&mMappingDataBase);\r
1308 UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
1309 }\r
1310 //\r
1311 // Pass changed uncommitted data back to Form Browser\r
1312 //\r
1313 BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
1314 Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) FakeNvData, NULL);\r
1315\r
1316 return EFI_SUCCESS;\r
1317}\r
1318\r
1319/**\r
1320 Function unpacks a device path data structure so that all the nodes\r
1321 of a device path are naturally aligned.\r
1322\r
1323 @param DevPath A pointer to a device path data structure\r
1324\r
1325 @return If the memory for the device path is successfully allocated, then a\r
1326 @return pointer to the new device path is returned. Otherwise, NULL is returned.\r
1327\r
1328**/\r
1329EFI_DEVICE_PATH_PROTOCOL *\r
1330UnpackDevicePath (\r
1331 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
1332 )\r
1333{\r
1334 EFI_DEVICE_PATH_PROTOCOL *Src;\r
1335 EFI_DEVICE_PATH_PROTOCOL *Dest;\r
1336 EFI_DEVICE_PATH_PROTOCOL *NewPath;\r
1337 UINTN Size;\r
1338\r
1339 //\r
1340 // Walk device path and round sizes to valid boundries\r
1341 //\r
1342 Src = DevPath;\r
1343 Size = 0;\r
1344 for (;;) {\r
1345 Size += DevicePathNodeLength (Src);\r
1346 Size += ALIGN_SIZE (Size);\r
1347\r
1348 if (IsDevicePathEnd (Src)) {\r
1349 break;\r
1350 }\r
1351\r
1352 Src = NextDevicePathNode (Src);\r
1353 }\r
1354 //\r
1355 // Allocate space for the unpacked path\r
1356 //\r
1357 NewPath = AllocateZeroPool (Size);\r
1358 if (NewPath) {\r
1359\r
1360 ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
1361\r
1362 //\r
1363 // Copy each node\r
1364 //\r
1365 Src = DevPath;\r
1366 Dest = NewPath;\r
1367 for (;;) {\r
1368 Size = DevicePathNodeLength (Src);\r
1369 CopyMem (Dest, Src, Size);\r
1370 Size += ALIGN_SIZE (Size);\r
1371 SetDevicePathNodeLength (Dest, Size);\r
1372 Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
1373 Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
1374\r
1375 if (IsDevicePathEnd (Src)) {\r
1376 break;\r
1377 }\r
1378\r
1379 Src = NextDevicePathNode (Src);\r
1380 }\r
1381 }\r
1382\r
1383 return NewPath;\r
1384}\r
1385\r
1386\r
1387/**\r
1388 Get the description string by device path.\r
1389\r
1390 @param DevPath The input device path.\r
1391\r
1392 @retval !NULL The description string retured.\r
1393 @retval NULL The description string cannot be found.\r
1394\r
1395**/\r
1396CHAR16 *\r
1397DevicePathToStr (\r
1398 IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
1399 )\r
1400{\r
1401 EFI_STATUS Status;\r
1402 CHAR16 *ToText;\r
1403 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
1404\r
1405 if (DevPath == NULL) {\r
1406 return NULL;\r
1407 }\r
1408\r
1409 Status = gBS->LocateProtocol (\r
1410 &gEfiDevicePathToTextProtocolGuid,\r
1411 NULL,\r
1412 (VOID **) &DevPathToText\r
1413 );\r
1414 if (!EFI_ERROR (Status)) {\r
1415 ToText = DevPathToText->ConvertDevicePathToText (\r
1416 DevPath,\r
1417 FALSE,\r
1418 TRUE\r
1419 );\r
1420 ASSERT (ToText != NULL);\r
1421 return ToText;\r
1422 }\r
1423\r
1424 return NULL;\r
1425}\r