3 Copyright (c) 2007 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 A UI driver to offer a UI interface in device manager to let user configue
19 platform override protocol to override the default algorithm for matching
20 drivers to controllers.
23 1. The UI driver dynamicly locate all controller device path.
24 2. The UI driver dynamicly locate all drivers which support binding protocol.
25 3. The UI driver export and dynamicly update two menu to let user select the
26 mapping between drivers to controllers.
27 4. The UI driver save all the mapping info in NV variables which will be consumed
28 by platform override protocol driver to publish the platform override protocol.
32 #include "PlatOverMngr.h"
34 STATIC EFI_GUID mPlatformOverridesManagerGuid
= PLAT_OVER_MNGR_GUID
;
36 STATIC LIST_ENTRY mMappingDataBase
= INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase
);
38 STATIC EFI_HANDLE
*mDevicePathHandleBuffer
;
39 STATIC EFI_HANDLE
*mDriverImageHandleBuffer
;
41 STATIC UINTN mSelectedCtrIndex
;
42 STATIC EFI_STRING_ID mControllerToken
[MAX_CHOICE_NUM
];
44 STATIC UINTN mDriverImageHandleCount
;
45 STATIC EFI_STRING_ID mDriverImageToken
[MAX_CHOICE_NUM
];
46 STATIC EFI_STRING_ID mDriverImageFilePathToken
[MAX_CHOICE_NUM
];
47 STATIC EFI_LOADED_IMAGE_PROTOCOL
*mDriverImageProtocol
[MAX_CHOICE_NUM
];
48 STATIC EFI_DEVICE_PATH_PROTOCOL
*mControllerDevicePathProtocol
[MAX_CHOICE_NUM
];
49 STATIC UINTN mSelectedDriverImageNum
;
50 STATIC UINTN mLastSavedDriverImageNum
;
51 STATIC CHAR8 mLanguage
[RFC_3066_ENTRY_SIZE
];
52 STATIC UINT16 mCurrentPage
;
55 The driver Entry Point. The funciton will export a disk device class formset and
56 its callback function to hii database.
58 @param ImageHandle The firmware allocated handle for the EFI image.
59 @param SystemTable A pointer to the EFI System Table.
61 @retval EFI_SUCCESS The entry point is executed successfully.
62 @retval other Some error occurs when executing this entry point.
68 IN EFI_HANDLE ImageHandle
,
69 IN EFI_SYSTEM_TABLE
*SystemTable
73 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
74 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
75 EFI_CALLBACK_INFO
*CallbackInfo
;
76 EFI_HANDLE DriverHandle
;
77 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
80 // There should only be one HII protocol
82 Status
= gBS
->LocateProtocol (
83 &gEfiHiiDatabaseProtocolGuid
,
85 (VOID
**) &HiiDatabase
87 if (EFI_ERROR (Status
)) {
93 // There should only be one Form Configuration protocol
95 Status
= gBS
->LocateProtocol (
96 &gEfiFormBrowser2ProtocolGuid
,
98 (VOID
**) &FormBrowser2
100 if (EFI_ERROR (Status
)) {
105 CallbackInfo
= AllocateZeroPool (sizeof (EFI_CALLBACK_INFO
));
106 if (CallbackInfo
== NULL
) {
107 return EFI_BAD_BUFFER_SIZE
;
110 CallbackInfo
->Signature
= EFI_CALLBACK_INFO_SIGNATURE
;
111 CallbackInfo
->ConfigAccess
.ExtractConfig
= PlatOverMngrExtractConfig
;
112 CallbackInfo
->ConfigAccess
.RouteConfig
= PlatOverMngrRouteConfig
;
113 CallbackInfo
->ConfigAccess
.Callback
= PlatOverMngrCallback
;
116 // Create driver handle used by HII database
118 Status
= HiiLibCreateHiiDriverHandle (&DriverHandle
);
119 if (EFI_ERROR (Status
)) {
122 CallbackInfo
->DriverHandle
= DriverHandle
;
125 // Install Config Access protocol to driver handle
127 Status
= gBS
->InstallProtocolInterface (
129 &gEfiHiiConfigAccessProtocolGuid
,
130 EFI_NATIVE_INTERFACE
,
131 &CallbackInfo
->ConfigAccess
133 if (EFI_ERROR (Status
)) {
138 // Publish our HII data
140 PackageList
= HiiLibPreparePackageList (
142 &mPlatformOverridesManagerGuid
,
146 ASSERT (PackageList
!= NULL
);
148 Status
= HiiDatabase
->NewPackageList (
152 &CallbackInfo
->RegisteredHandle
154 gBS
->FreePool (PackageList
);
157 // Locate ConfigRouting protocol
159 Status
= gBS
->LocateProtocol (
160 &gEfiHiiConfigRoutingProtocolGuid
,
162 (VOID
**) &CallbackInfo
->HiiConfigRouting
164 if (EFI_ERROR (Status
)) {
169 // Clear all the globle variable
171 mDriverImageHandleCount
= 0;
173 ZeroMem (mDriverImageToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
174 ZeroMem (mDriverImageFilePathToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
175 ZeroMem (mControllerToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
176 ZeroMem (mDriverImageProtocol
, MAX_CHOICE_NUM
* sizeof (EFI_LOADED_IMAGE_PROTOCOL
*));
182 Do some convertion for the ComponentName2 supported language. It do
183 the convertion just for english language code currently.
185 @param ComponentName Pointer to the ComponentName2 protocl pointer.
186 @param Language The language string.
188 @return Return the duplication of Language if it is not english otherwise return
189 the supported english language code.
193 ConvertComponentName2SupportLanguage (
194 IN EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName
,
198 CHAR8
*SupportedLanguages
;
203 SupportedLanguages
= NULL
;
206 // treat all the english language code (en-xx or eng) equally
208 if ((AsciiStrnCmp (Language
, "en-", 3) == 0) || (AsciiStrCmp (Language
, "eng") == 0)) {
209 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "en");
210 if (SupportedLanguages
== NULL
) {
211 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "eng");
216 // duplicate the Language if it is not english
218 if (SupportedLanguages
== NULL
) {
219 SupportedLanguages
= Language
;
223 // duplicate the returned language code.
225 if (AsciiStrStr (SupportedLanguages
, "-") != NULL
) {
226 LangCode
= AllocateZeroPool(32);
227 for(Index
= 0; (Index
< 31) && (SupportedLanguages
[Index
] != '\0') && (SupportedLanguages
[Index
] != ';'); Index
++) {
228 LangCode
[Index
] = SupportedLanguages
[Index
];
230 LangCode
[Index
] = '\0';
232 LangCode
= AllocateZeroPool(4);
233 for(Index
= 0; (Index
< 3) && (SupportedLanguages
[Index
] != '\0'); Index
++) {
234 LangCode
[Index
] = SupportedLanguages
[Index
];
236 LangCode
[Index
] = '\0';
242 Get the ComponentName or ComponentName2 protocol according to the driver binding handle
244 @param DriverBindingHandle The Handle of DriverBinding.
246 @retval !NULL Pointer into the image name if the image name is found,
247 @retval NULL Pointer to NULL if the image name is not found.
252 IN EFI_HANDLE DriverBindingHandle
256 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
257 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
258 CHAR8
*SupportedLanguage
;
261 ComponentName
= NULL
;
262 ComponentName2
= NULL
;
263 Status
= gBS
->OpenProtocol (
265 &gEfiComponentName2ProtocolGuid
,
266 (VOID
**) &ComponentName2
,
269 EFI_OPEN_PROTOCOL_GET_PROTOCOL
271 if (EFI_ERROR(Status
)) {
272 Status
= gBS
->OpenProtocol (
274 &gEfiComponentNameProtocolGuid
,
275 (VOID
**) &ComponentName
,
278 EFI_OPEN_PROTOCOL_GET_PROTOCOL
282 Status
= EFI_SUCCESS
;
284 if (ComponentName
!= NULL
) {
285 if (ComponentName
->GetDriverName
!= NULL
) {
286 Status
= ComponentName
->GetDriverName (
292 } else if (ComponentName2
!= NULL
) {
293 if (ComponentName2
->GetDriverName
!= NULL
) {
294 SupportedLanguage
= ConvertComponentName2SupportLanguage (ComponentName2
, mLanguage
);
295 Status
= ComponentName2
->GetDriverName (
300 gBS
->FreePool (SupportedLanguage
);
303 if (EFI_ERROR (Status
)) {
313 @param Image Image to search.
315 @retval !NULL Pointer into the image name if the image name is found,
316 @retval NULL Pointer to NULL if the image name is not found.
321 EFI_LOADED_IMAGE_PROTOCOL
*Image
325 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
326 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
327 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
330 UINT32 AuthenticationStatus
;
332 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FV2
;
338 if (Image
->FilePath
== NULL
) {
342 DevPath
= UnpackDevicePath (Image
->FilePath
);
344 if (DevPath
== NULL
) {
348 DevPathNode
= DevPath
;
350 while (!IsDevicePathEnd (DevPathNode
)) {
352 // Find the Fv File path
354 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)DevPathNode
);
355 if (NameGuid
!= NULL
) {
356 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) DevPathNode
;
357 Status
= gBS
->HandleProtocol (
359 &gEfiFirmwareVolume2ProtocolGuid
,
362 if (!EFI_ERROR (Status
)) {
363 Status
= FV2
->ReadSection (
365 &FvFilePath
->FvFileName
,
366 EFI_SECTION_USER_INTERFACE
,
370 &AuthenticationStatus
372 if (!EFI_ERROR (Status
)) {
379 // Next device path node
381 DevPathNode
= NextDevicePathNode (DevPathNode
);
384 gBS
->FreePool (DevPath
);
389 Prepare the first page to let user select the device controller which need to
392 @param Private Pointer to EFI_CALLBACK_INFO.
393 @param KeyValue The callback key value of device controller item in first page.
394 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
396 @retval EFI_SUCCESS Always returned.
400 UpdateDeviceSelectPage (
401 IN EFI_CALLBACK_INFO
*Private
,
403 IN PLAT_OVER_MNGR_DATA
*FakeNvData
406 EFI_HII_UPDATE_DATA UpdateData
;
410 UINTN DevicePathHandleCount
;
412 EFI_STRING_ID NewStringToken
;
413 CHAR16
*ControllerName
;
414 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
415 EFI_PCI_IO_PROTOCOL
*PciIo
;
416 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
419 mCurrentPage
= FORM_ID_DEVICE
;
421 // Following code will be run if user select 'Refresh' in first page
422 // During first page, user will see all currnet controller device path in system,
423 // select any device path will go to second page to select its overrides drivers
426 LangSize
= RFC_3066_ENTRY_SIZE
;
427 Status
= gRT
->GetVariable (
429 &gEfiGlobalVariableGuid
,
434 ASSERT_EFI_ERROR (Status
);
437 // Initial the mapping database in memory
439 FreeMappingDatabase (&mMappingDataBase
);
440 Status
= InitOverridesMapping (&mMappingDataBase
);
443 // Clear all the content in the first page
445 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
446 UpdateData
.Offset
= 0;
447 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
448 ASSERT (UpdateData
.Data
!= NULL
);
450 // Clear first page form
453 Private
->RegisteredHandle
,
454 &mPlatformOverridesManagerGuid
,
462 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
463 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
465 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH
);
466 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH
), &NewString
);
467 ASSERT (NewString
!= NULL
);
468 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
469 ASSERT_EFI_ERROR (Status
);
470 gBS
->FreePool (NewString
);
472 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH_HELP
);
473 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH_HELP
), &NewString
);
474 ASSERT (NewString
!= NULL
);
475 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
476 ASSERT_EFI_ERROR (Status
);
477 gBS
->FreePool (NewString
);
479 // created needed controller device item in first page
481 DevicePathHandleCount
= 0;
482 Status
= gBS
->LocateHandleBuffer (
484 &gEfiDevicePathProtocolGuid
,
486 &DevicePathHandleCount
,
487 &mDevicePathHandleBuffer
489 if (EFI_ERROR (Status
) || (DevicePathHandleCount
== 0)) {
493 for (Index
= 0; Index
< DevicePathHandleCount
; Index
++) {
494 if (FakeNvData
->PciDeviceFilter
== 0x01) {
496 // Only care PCI device which contain efi driver in its option rom.
500 // Check whether it is a pci device
502 ControllerDevicePath
= NULL
;
503 Status
= gBS
->OpenProtocol (
504 mDevicePathHandleBuffer
[Index
],
505 &gEfiPciIoProtocolGuid
,
509 EFI_OPEN_PROTOCOL_GET_PROTOCOL
511 if (EFI_ERROR (Status
)) {
515 // Check whether it contain efi driver in its option rom
517 Status
= gBS
->HandleProtocol(
518 mDevicePathHandleBuffer
[Index
],
519 &gEfiBusSpecificDriverOverrideProtocolGuid
,
520 (VOID
**) &BusSpecificDriverOverride
522 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
527 ControllerDevicePath
= NULL
;
528 Status
= gBS
->OpenProtocol (
529 mDevicePathHandleBuffer
[Index
],
530 &gEfiDevicePathProtocolGuid
,
531 (VOID
**) &ControllerDevicePath
,
534 EFI_OPEN_PROTOCOL_GET_PROTOCOL
536 ASSERT_EFI_ERROR (Status
);
538 // Save the device path protocol interface
540 mControllerDevicePathProtocol
[Index
] = ControllerDevicePath
;
543 // Get the driver name
545 ControllerName
= DevicePathToStr (ControllerDevicePath
);
548 // Export the driver name string and create item in set options page
550 Len
= StrSize (ControllerName
);
551 NewString
= AllocateZeroPool (Len
+ StrSize (L
"--"));
552 if (EFI_ERROR (CheckMapping (ControllerDevicePath
,NULL
, &mMappingDataBase
, NULL
, NULL
))) {
553 StrCat (NewString
, L
"--");
555 StrCat (NewString
, L
"**");
557 StrCat (NewString
, ControllerName
);
559 NewStringToken
= mControllerToken
[Index
];
560 if (NewStringToken
== 0) {
561 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
563 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
565 ASSERT_EFI_ERROR (Status
);
566 gBS
->FreePool (NewString
);
568 // Save the device path string toke for next access use
570 mControllerToken
[Index
] = NewStringToken
;
575 STRING_TOKEN (STR_GOTO_HELP_DRIVER
),
576 EFI_IFR_FLAG_CALLBACK
,
577 (UINT16
) (Index
+ KEY_VALUE_DEVICE_OFFSET
),
583 // Update first page form
586 Private
->RegisteredHandle
,
587 &mPlatformOverridesManagerGuid
,
594 gBS
->FreePool (UpdateData
.Data
);
599 Prepare to let user select the drivers which need mapping with the device controller
600 selected in first page.
602 @param Private Pointer to EFI_CALLBACK_INFO.
603 @param KeyValue The callback key value of device controller item in first page.
604 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
606 @retval EFI_SUCCESS Always returned.
610 UpdateBindingDriverSelectPage (
611 IN EFI_CALLBACK_INFO
*Private
,
613 IN PLAT_OVER_MNGR_DATA
*FakeNvData
616 EFI_HII_UPDATE_DATA UpdateData
;
621 EFI_STRING_ID NewStringToken
;
622 EFI_STRING_ID NewStringHelpToken
;
623 UINTN DriverImageHandleCount
;
625 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
626 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
628 BOOLEAN FreeDriverName
;
630 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
631 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
632 EFI_HANDLE DriverBindingHandle
;
634 // If user select a controller item in the first page the following code will be run.
635 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
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
638 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
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.
642 mCurrentPage
= FORM_ID_DRIVER
;
644 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
646 mSelectedCtrIndex
= KeyValue
- 0x100;
647 ASSERT (mSelectedCtrIndex
< MAX_CHOICE_NUM
);
648 mLastSavedDriverImageNum
= 0;
650 // Clear all the content in dynamic page
652 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
653 UpdateData
.Offset
= 0;
654 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
655 ASSERT (UpdateData
.Data
!= NULL
);
657 // Clear second page form
660 Private
->RegisteredHandle
,
661 &mPlatformOverridesManagerGuid
,
669 // Show all driver which support loaded image protocol in second page
671 DriverImageHandleCount
= 0;
672 Status
= gBS
->LocateHandleBuffer (
674 &gEfiLoadedImageProtocolGuid
,
676 &DriverImageHandleCount
,
677 &mDriverImageHandleBuffer
679 if (EFI_ERROR (Status
) || (DriverImageHandleCount
== 0)) {
680 return EFI_NOT_FOUND
;
683 mDriverImageHandleCount
= DriverImageHandleCount
;
684 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
686 // Step1: Get the driver image total file path for help string and the driver name.
690 // Find driver's Loaded Image protocol
694 Status
= gBS
->OpenProtocol (
695 mDriverImageHandleBuffer
[Index
],
696 &gEfiLoadedImageProtocolGuid
,
697 (VOID
**) &LoadedImage
,
700 EFI_OPEN_PROTOCOL_GET_PROTOCOL
702 if (EFI_ERROR (Status
)) {
703 FakeNvData
->DriSelection
[Index
] = 0x00;
706 mDriverImageProtocol
[Index
] = LoadedImage
;
708 // Find its related driver binding protocol
710 DriverBindingInterface
= NULL
;
711 DriverBindingHandle
= NULL
;
712 DriverBindingInterface
= GetBindingProtocolFromImageHandle (
713 mDriverImageHandleBuffer
[Index
],
716 if (DriverBindingInterface
== NULL
) {
717 FakeNvData
->DriSelection
[Index
] = 0x00;
722 // Get the EFI Loaded Image Device Path Protocol
724 LoadedImageDevicePath
= NULL
;
725 Status
= gBS
->HandleProtocol (
726 mDriverImageHandleBuffer
[Index
],
727 &gEfiLoadedImageDevicePathProtocolGuid
,
728 (VOID
**) &LoadedImageDevicePath
730 if (LoadedImageDevicePath
== NULL
) {
731 FakeNvData
->DriSelection
[Index
] = 0x00;
735 if (FakeNvData
->PciDeviceFilter
== 0x01) {
737 // only care the driver which is in a Pci device option rom,
738 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
740 if (!EFI_ERROR (Status
)) {
741 Status
= gBS
->HandleProtocol(
742 LoadedImage
->DeviceHandle
,
743 &gEfiBusSpecificDriverOverrideProtocolGuid
,
744 (VOID
**) &BusSpecificDriverOverride
746 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
747 FakeNvData
->DriSelection
[Index
] = 0x00;
751 FakeNvData
->DriSelection
[Index
] = 0x00;
757 // For driver name, try to get its component name, if fail, get its image name,
758 // if also fail, give a default name.
760 FreeDriverName
= FALSE
;
761 DriverName
= GetComponentName (DriverBindingHandle
);
762 if (DriverName
== NULL
) {
764 // get its image name
766 DriverName
= GetImageName (LoadedImage
);
768 if (DriverName
== NULL
) {
770 // give a default name
772 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME
), &DriverName
);
773 ASSERT (DriverName
!= NULL
);
774 FreeDriverName
= TRUE
; // the DriverName string need to free pool
779 // Step2 Export the driver name string and create check box item in second page
783 // First create the driver image name
785 NewString
= AllocateZeroPool (StrSize (DriverName
));
786 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol
[mSelectedCtrIndex
], LoadedImageDevicePath
, &mMappingDataBase
, NULL
, NULL
))) {
787 FakeNvData
->DriSelection
[Index
] = 0x00;
789 FakeNvData
->DriSelection
[Index
] = 0x01;
790 mLastSavedDriverImageNum
++;
792 StrCat (NewString
, DriverName
);
793 NewStringToken
= mDriverImageToken
[Index
];
794 if (NewStringToken
== 0) {
795 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
797 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
799 mDriverImageToken
[Index
] = NewStringToken
;
800 ASSERT_EFI_ERROR (Status
);
801 gBS
->FreePool (NewString
);
802 if (FreeDriverName
) {
803 gBS
->FreePool (DriverName
);
807 // Second create the driver image device path as item help string
809 DriverName
= DevicePathToStr (LoadedImageDevicePath
);
811 NewString
= AllocateZeroPool (StrSize (DriverName
));
812 StrCat (NewString
, DriverName
);
813 NewStringHelpToken
= mDriverImageFilePathToken
[Index
];
814 if (NewStringHelpToken
== 0) {
815 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringHelpToken
, NewString
);
817 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringHelpToken
, NewString
);
819 mDriverImageFilePathToken
[Index
] = NewStringHelpToken
;
820 ASSERT_EFI_ERROR (Status
);
821 gBS
->FreePool (NewString
);
822 gBS
->FreePool (DriverName
);
824 CreateCheckBoxOpCode (
825 (UINT16
) (DRIVER_SELECTION_QUESTION_ID
+ Index
),
826 VARSTORE_ID_PLAT_OVER_MNGR
,
827 (UINT16
) (DRIVER_SELECTION_VAR_OFFSET
+ Index
),
837 // Update second page form
840 Private
->RegisteredHandle
,
841 &mPlatformOverridesManagerGuid
,
848 gBS
->FreePool (UpdateData
.Data
);
853 Prepare to let user select the priority order of the drivers which are
854 selected in second page.
856 @param Private Pointer to EFI_CALLBACK_INFO.
857 @param KeyValue The callback key value of device controller item in first page.
858 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
860 @retval EFI_SUCCESS Always returned.
864 UpdatePrioritySelectPage (
865 IN EFI_CALLBACK_INFO
*Private
,
867 IN PLAT_OVER_MNGR_DATA
*FakeNvData
870 EFI_HII_UPDATE_DATA UpdateData
;
873 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
875 IFR_OPTION
*IfrOptionList
;
876 UINTN SelectedDriverImageNum
;
877 UINT32 DriverImageNO
;
883 // Following code will be run if user select 'order ... priority' item in second page
884 // Prepare third page. In third page, user will order the drivers priority which are selected in second page
886 mCurrentPage
= FORM_ID_ORDER
;
888 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
889 UpdateData
.Offset
= 0;
890 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
891 ASSERT (UpdateData
.Data
!= NULL
);
893 // Clear third page form
896 Private
->RegisteredHandle
,
897 &mPlatformOverridesManagerGuid
,
905 // Check how many drivers have been selected
907 SelectedDriverImageNum
= 0;
908 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
909 if (FakeNvData
->DriSelection
[Index
] != 0) {
910 SelectedDriverImageNum
++;
914 mSelectedDriverImageNum
= SelectedDriverImageNum
;
915 if (SelectedDriverImageNum
== 0) {
919 IfrOptionList
= AllocateZeroPool (0x200);
920 ASSERT_EFI_ERROR (IfrOptionList
!= NULL
);
922 // Create order list for those selected drivers
924 SelectedDriverImageNum
= 0;
925 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
926 if (FakeNvData
->DriSelection
[Index
] != 0) {
927 IfrOptionList
[SelectedDriverImageNum
].StringToken
= mDriverImageToken
[Index
];
929 // Use the NO. in driver binding buffer as value, will use it later
931 IfrOptionList
[SelectedDriverImageNum
].Value
.u8
= (UINT8
) (Index
+ 1);
932 IfrOptionList
[SelectedDriverImageNum
].Flags
= 0;
935 // Get the EFI Loaded Image Device Path Protocol
937 LoadedImageDevicePath
= NULL
;
938 gBS
->HandleProtocol (
939 mDriverImageHandleBuffer
[Index
],
940 &gEfiLoadedImageDevicePathProtocolGuid
,
941 (VOID
**) &LoadedImageDevicePath
943 ASSERT (LoadedImageDevicePath
!= NULL
);
946 // Check the driver DriverImage's order number in mapping database
950 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
951 LoadedImageDevicePath
,
956 if (DriverImageNO
== 0) {
957 DriverImageNO
= (UINT32
) mLastSavedDriverImageNum
+ 1;
958 mLastSavedDriverImageNum
++;
960 TempNO
[SelectedDriverImageNum
] = DriverImageNO
;
961 SelectedDriverImageNum
++;
965 ASSERT (SelectedDriverImageNum
== mSelectedDriverImageNum
);
967 // NvRamMap Must be clear firstly
969 ZeroMem (FakeNvData
->DriOrder
, 100);
972 // Order the selected drivers according to the info already in mapping database
973 // the less order number in mapping database the less order number in NvRamMap
975 for (Index
=0; Index
< SelectedDriverImageNum
; Index
++) {
977 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
980 for (Index1
=0; Index1
< SelectedDriverImageNum
; Index1
++) {
981 if (TempNO
[Index1
] < TempNO
[MinNO
]) {
986 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
988 FakeNvData
->DriOrder
[Index
] =IfrOptionList
[MinNO
].Value
.u8
;
992 CreateOrderedListOpCode (
993 (UINT16
) DRIVER_ORDER_QUESTION_ID
,
994 VARSTORE_ID_PLAT_OVER_MNGR
,
995 (UINT16
) DRIVER_ORDER_VAR_OFFSET
,
996 mControllerToken
[mSelectedCtrIndex
],
997 mControllerToken
[mSelectedCtrIndex
],
998 EFI_IFR_FLAG_RESET_REQUIRED
,
1000 EFI_IFR_NUMERIC_SIZE_1
,
1003 SelectedDriverImageNum
,
1008 // Update third page form
1011 Private
->RegisteredHandle
,
1012 &mPlatformOverridesManagerGuid
,
1019 gBS
->FreePool (IfrOptionList
);
1020 gBS
->FreePool (UpdateData
.Data
);
1025 Save the save the mapping database to NV variable.
1027 @param Private Pointer to EFI_CALLBACK_INFO.
1028 @param KeyValue The callback key value of device controller item in first page.
1029 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
1031 @retval EFI_SUCCESS Always returned.
1036 IN EFI_CALLBACK_INFO
*Private
,
1038 IN PLAT_OVER_MNGR_DATA
*FakeNvData
1043 UINTN SelectedDriverImageNum
;
1044 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1046 // Following code will be run if user select 'commint changes' in third page
1047 // user enter 'Commit Changes' to save the mapping database
1049 DeleteDriverImage (mControllerDevicePathProtocol
[mSelectedCtrIndex
], NULL
, &mMappingDataBase
);
1050 for (SelectedDriverImageNum
= 0; SelectedDriverImageNum
< mSelectedDriverImageNum
; SelectedDriverImageNum
++) {
1052 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
1054 Index
= FakeNvData
->DriOrder
[SelectedDriverImageNum
] - 1;
1057 // Get the EFI Loaded Image Device Path Protocol
1059 LoadedImageDevicePath
= NULL
;
1060 Status
= gBS
->HandleProtocol (
1061 mDriverImageHandleBuffer
[Index
],
1062 &gEfiLoadedImageDevicePathProtocolGuid
,
1063 (VOID
**) &LoadedImageDevicePath
1065 ASSERT (LoadedImageDevicePath
!= NULL
);
1068 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
1069 LoadedImageDevicePath
,
1071 (UINT32
)SelectedDriverImageNum
+ 1
1074 Status
= SaveOverridesMapping (&mMappingDataBase
);
1080 This function allows a caller to extract the current configuration for one
1081 or more named elements from the target driver.
1083 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1084 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1085 @param Progress On return, points to a character in the Request string.
1086 Points to the string's null terminator if request was successful.
1087 Points to the most recent '&' before the first failing name/value
1088 pair (or the beginning of the string if the failure is in the
1089 first name/value pair) if the request was not successful.
1090 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
1091 has all values filled in for the names in the Request string.
1092 String to be allocated by the called function.
1094 @retval EFI_SUCCESS The Results is filled with the requested values.
1095 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
1096 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
1097 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1102 PlatOverMngrExtractConfig (
1103 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1104 IN CONST EFI_STRING Request
,
1105 OUT EFI_STRING
*Progress
,
1106 OUT EFI_STRING
*Results
1110 EFI_CALLBACK_INFO
*Private
;
1111 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1113 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1114 HiiConfigRouting
= Private
->HiiConfigRouting
;
1117 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1119 Status
= HiiConfigRouting
->BlockToConfig (
1122 (UINT8
*) &Private
->FakeNvData
,
1123 sizeof (PLAT_OVER_MNGR_DATA
),
1131 This function processes the results of changes in configuration.
1133 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1134 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1135 @param Progress A pointer to a string filled in with the offset of the most
1136 recent '&' before the first failing name/value pair (or the
1137 beginning of the string if the failure is in the first
1138 name/value pair) or the terminating NULL if all was successful.
1140 @retval EFI_SUCCESS The Results is processed successfully.
1141 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1142 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1147 PlatOverMngrRouteConfig (
1148 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1149 IN CONST EFI_STRING Configuration
,
1150 OUT EFI_STRING
*Progress
1153 EFI_CALLBACK_INFO
*Private
;
1157 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1159 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1161 FakeNvData
= &Private
->FakeNvData
;
1162 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1163 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1164 if (EFI_ERROR (Status
)) {
1168 if (mCurrentPage
== FORM_ID_DRIVER
) {
1169 KeyValue
= KEY_VALUE_DRIVER_GOTO_ORDER
;
1170 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1171 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1172 CommintChanges (Private
, KeyValue
, FakeNvData
);
1174 // Since UpdatePrioritySelectPage will change mCurrentPage,
1175 // should ensure the mCurrentPage still indicate the second page here
1177 mCurrentPage
= FORM_ID_DRIVER
;
1180 if (mCurrentPage
== FORM_ID_ORDER
) {
1181 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1182 CommintChanges (Private
, KeyValue
, FakeNvData
);
1188 This is the function that is called to provide results data to the driver. This data
1189 consists of a unique key which is used to identify what data is either being passed back
1192 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1193 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1194 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1195 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1196 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1197 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1198 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1199 KeyValue == 0x1800 : user select 'commint changes' in third page
1200 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1201 @param Type The type of value for the question.
1202 @param Value A pointer to the data being sent to the original exporting driver.
1203 @param ActionRequest On return, points to the action requested by the callback function.
1205 @retval EFI_SUCCESS Always returned.
1210 PlatOverMngrCallback (
1211 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1212 IN EFI_BROWSER_ACTION Action
,
1213 IN EFI_QUESTION_ID KeyValue
,
1215 IN EFI_IFR_TYPE_VALUE
*Value
,
1216 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1219 EFI_CALLBACK_INFO
*Private
;
1221 EFI_STRING_ID NewStringToken
;
1223 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1226 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1228 FakeNvData
= &Private
->FakeNvData
;
1229 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1230 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1231 if (EFI_ERROR (Status
)) {
1235 if (KeyValue
== KEY_VALUE_DEVICE_REFRESH
||
1236 KeyValue
== KEY_VALUE_DEVICE_FILTER
||
1237 KeyValue
== KEY_VALUE_DRIVER_GOTO_PREVIOUS
1239 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1241 // Update page title string
1243 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1244 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"First, Select the controller by device path");
1245 ASSERT_EFI_ERROR (Status
);
1248 if (((KEY_VALUE_DEVICE_OFFSET
<= KeyValue
) && (KeyValue
< KEY_VALUE_DEVICE_MAX
)) || (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
)) {
1249 if (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
) {
1250 KeyValue
= (EFI_QUESTION_ID
) (mSelectedCtrIndex
+ 0x100);
1252 UpdateBindingDriverSelectPage (Private
, KeyValue
, FakeNvData
);
1254 // Update page title string
1256 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1257 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Second, Select drivers for the previous selected controller");
1258 ASSERT_EFI_ERROR (Status
);
1261 if (KeyValue
== KEY_VALUE_DRIVER_GOTO_ORDER
) {
1262 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1264 // Update page title string
1266 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1267 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Finally, Set the priority order for the drivers and save them");
1268 ASSERT_EFI_ERROR (Status
);
1271 if (KeyValue
== KEY_VALUE_ORDER_SAVE_AND_EXIT
) {
1272 Status
= CommintChanges (Private
, KeyValue
, FakeNvData
);
1273 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1274 if (EFI_ERROR (Status
)) {
1275 IfrLibCreatePopUp (1, &Key
, L
"Single Override Info too large, Saving Error!");
1276 return EFI_DEVICE_ERROR
;
1280 if (KeyValue
== KEY_VALUE_DEVICE_CLEAR
) {
1282 // Deletes all environment variable(s) that contain the override mappings info
1284 FreeMappingDatabase (&mMappingDataBase
);
1285 Status
= SaveOverridesMapping (&mMappingDataBase
);
1286 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1289 // Pass changed uncommitted data back to Form Browser
1291 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1292 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) FakeNvData
, NULL
);
1298 Function unpacks a device path data structure so that all the nodes
1299 of a device path are naturally aligned.
1301 @param DevPath A pointer to a device path data structure
1303 @return If the memory for the device path is successfully allocated, then a
1304 @return pointer to the new device path is returned. Otherwise, NULL is returned.
1307 EFI_DEVICE_PATH_PROTOCOL
*
1309 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1312 EFI_DEVICE_PATH_PROTOCOL
*Src
;
1313 EFI_DEVICE_PATH_PROTOCOL
*Dest
;
1314 EFI_DEVICE_PATH_PROTOCOL
*NewPath
;
1318 // Walk device path and round sizes to valid boundries
1323 Size
+= DevicePathNodeLength (Src
);
1324 Size
+= ALIGN_SIZE (Size
);
1326 if (IsDevicePathEnd (Src
)) {
1330 Src
= NextDevicePathNode (Src
);
1333 // Allocate space for the unpacked path
1335 NewPath
= AllocateZeroPool (Size
);
1338 ASSERT (((UINTN
) NewPath
) % MIN_ALIGNMENT_SIZE
== 0);
1346 Size
= DevicePathNodeLength (Src
);
1347 CopyMem (Dest
, Src
, Size
);
1348 Size
+= ALIGN_SIZE (Size
);
1349 SetDevicePathNodeLength (Dest
, Size
);
1350 Dest
->Type
|= EFI_DP_TYPE_UNPACKED
;
1351 Dest
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) Dest
) + Size
);
1353 if (IsDevicePathEnd (Src
)) {
1357 Src
= NextDevicePathNode (Src
);
1366 Get the description string by device path.
1368 @param DevPath The input device path.
1370 @retval !NULL The description string retured.
1371 @retval NULL The description string cannot be found.
1376 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1381 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
1383 if (DevPath
== NULL
) {
1387 Status
= gBS
->LocateProtocol (
1388 &gEfiDevicePathToTextProtocolGuid
,
1390 (VOID
**) &DevPathToText
1392 if (!EFI_ERROR (Status
)) {
1393 ToText
= DevPathToText
->ConvertDevicePathToText (
1398 ASSERT (ToText
!= NULL
);