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 EFI_GUID mPlatformOverridesManagerGuid
= PLAT_OVER_MNGR_GUID
;
36 LIST_ENTRY mMappingDataBase
= INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase
);
38 EFI_HANDLE
*mDevicePathHandleBuffer
;
39 EFI_HANDLE
*mDriverImageHandleBuffer
;
41 UINTN mSelectedCtrIndex
;
42 EFI_STRING_ID mControllerToken
[MAX_CHOICE_NUM
];
44 UINTN mDriverImageHandleCount
;
45 EFI_STRING_ID mDriverImageToken
[MAX_CHOICE_NUM
];
46 EFI_STRING_ID mDriverImageFilePathToken
[MAX_CHOICE_NUM
];
47 EFI_LOADED_IMAGE_PROTOCOL
*mDriverImageProtocol
[MAX_CHOICE_NUM
];
48 EFI_DEVICE_PATH_PROTOCOL
*mControllerDevicePathProtocol
[MAX_CHOICE_NUM
];
49 UINTN mSelectedDriverImageNum
;
50 UINTN mLastSavedDriverImageNum
;
51 CHAR8 mLanguage
[RFC_3066_ENTRY_SIZE
];
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
*));
181 Status
= FormBrowser2
->SendForm (
183 &CallbackInfo
->RegisteredHandle
,
191 Status
= HiiDatabase
->RemovePackageList (HiiDatabase
, CallbackInfo
->RegisteredHandle
);
192 if (EFI_ERROR (Status
)) {
200 Do some convertion for the ComponentName2 supported language. It do
201 the convertion just for english language code currently.
203 @param ComponentName Pointer to the ComponentName2 protocl pointer.
204 @param Language The language string.
206 @return Return the duplication of Language if it is not english otherwise return
207 the supported english language code.
211 ConvertComponentName2SupportLanguage (
212 IN EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName
,
216 CHAR8
*SupportedLanguages
;
221 SupportedLanguages
= NULL
;
224 // treat all the english language code (en-xx or eng) equally
226 if ((AsciiStrnCmp (Language
, "en-", 3) == 0) || (AsciiStrCmp (Language
, "eng") == 0)) {
227 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "en");
228 if (SupportedLanguages
== NULL
) {
229 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "eng");
234 // duplicate the Language if it is not english
236 if (SupportedLanguages
== NULL
) {
237 SupportedLanguages
= Language
;
241 // duplicate the returned language code.
243 if (AsciiStrStr (SupportedLanguages
, "-") != NULL
) {
244 LangCode
= AllocateZeroPool(32);
245 for(Index
= 0; (Index
< 31) && (SupportedLanguages
[Index
] != '\0') && (SupportedLanguages
[Index
] != ';'); Index
++) {
246 LangCode
[Index
] = SupportedLanguages
[Index
];
248 LangCode
[Index
] = '\0';
250 LangCode
= AllocateZeroPool(4);
251 for(Index
= 0; (Index
< 3) && (SupportedLanguages
[Index
] != '\0'); Index
++) {
252 LangCode
[Index
] = SupportedLanguages
[Index
];
254 LangCode
[Index
] = '\0';
260 Get the ComponentName or ComponentName2 protocol according to the driver binding handle
262 @param DriverBindingHandle The Handle of DriverBinding.
264 @retval !NULL Pointer into the image name if the image name is found,
265 @retval NULL Pointer to NULL if the image name is not found.
270 IN EFI_HANDLE DriverBindingHandle
274 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
275 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
276 CHAR8
*SupportedLanguage
;
279 ComponentName
= NULL
;
280 ComponentName2
= NULL
;
281 Status
= gBS
->OpenProtocol (
283 &gEfiComponentName2ProtocolGuid
,
284 (VOID
**) &ComponentName2
,
287 EFI_OPEN_PROTOCOL_GET_PROTOCOL
289 if (EFI_ERROR(Status
)) {
290 Status
= gBS
->OpenProtocol (
292 &gEfiComponentNameProtocolGuid
,
293 (VOID
**) &ComponentName
,
296 EFI_OPEN_PROTOCOL_GET_PROTOCOL
300 Status
= EFI_SUCCESS
;
302 if (ComponentName
!= NULL
) {
303 if (ComponentName
->GetDriverName
!= NULL
) {
304 Status
= ComponentName
->GetDriverName (
310 } else if (ComponentName2
!= NULL
) {
311 if (ComponentName2
->GetDriverName
!= NULL
) {
312 SupportedLanguage
= ConvertComponentName2SupportLanguage (ComponentName2
, mLanguage
);
313 Status
= ComponentName2
->GetDriverName (
318 gBS
->FreePool (SupportedLanguage
);
321 if (EFI_ERROR (Status
)) {
331 @param Image Image to search.
333 @retval !NULL Pointer into the image name if the image name is found,
334 @retval NULL Pointer to NULL if the image name is not found.
339 EFI_LOADED_IMAGE_PROTOCOL
*Image
343 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
344 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
345 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
348 UINT32 AuthenticationStatus
;
350 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FV2
;
356 if (Image
->FilePath
== NULL
) {
360 DevPath
= UnpackDevicePath (Image
->FilePath
);
362 if (DevPath
== NULL
) {
366 DevPathNode
= DevPath
;
368 while (!IsDevicePathEnd (DevPathNode
)) {
370 // Find the Fv File path
372 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)DevPathNode
);
373 if (NameGuid
!= NULL
) {
374 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) DevPathNode
;
375 Status
= gBS
->HandleProtocol (
377 &gEfiFirmwareVolume2ProtocolGuid
,
380 if (!EFI_ERROR (Status
)) {
381 Status
= FV2
->ReadSection (
383 &FvFilePath
->FvFileName
,
384 EFI_SECTION_USER_INTERFACE
,
388 &AuthenticationStatus
390 if (!EFI_ERROR (Status
)) {
397 // Next device path node
399 DevPathNode
= NextDevicePathNode (DevPathNode
);
402 gBS
->FreePool (DevPath
);
407 Prepare the first page to let user select the device controller which need to
410 @param Private Pointer to EFI_CALLBACK_INFO.
411 @param KeyValue The callback key value of device controller item in first page.
412 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
414 @retval EFI_SUCCESS Always returned.
418 UpdateDeviceSelectPage (
419 IN EFI_CALLBACK_INFO
*Private
,
421 IN PLAT_OVER_MNGR_DATA
*FakeNvData
424 EFI_HII_UPDATE_DATA UpdateData
;
428 UINTN DevicePathHandleCount
;
430 EFI_STRING_ID NewStringToken
;
431 CHAR16
*ControllerName
;
432 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
433 EFI_PCI_IO_PROTOCOL
*PciIo
;
434 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
437 mCurrentPage
= FORM_ID_DEVICE
;
439 // Following code will be run if user select 'Refresh' in first page
440 // During first page, user will see all currnet controller device path in system,
441 // select any device path will go to second page to select its overrides drivers
444 LangSize
= RFC_3066_ENTRY_SIZE
;
445 Status
= gRT
->GetVariable (
447 &gEfiGlobalVariableGuid
,
452 ASSERT_EFI_ERROR (Status
);
455 // Initial the mapping database in memory
457 FreeMappingDatabase (&mMappingDataBase
);
458 Status
= InitOverridesMapping (&mMappingDataBase
);
461 // Clear all the content in the first page
463 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
464 UpdateData
.Offset
= 0;
465 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
466 ASSERT (UpdateData
.Data
!= NULL
);
468 // Clear first page form
471 Private
->RegisteredHandle
,
472 &mPlatformOverridesManagerGuid
,
480 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
481 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
483 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH
);
484 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH
), &NewString
);
485 ASSERT (NewString
!= NULL
);
486 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
487 ASSERT_EFI_ERROR (Status
);
488 gBS
->FreePool (NewString
);
490 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH_HELP
);
491 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH_HELP
), &NewString
);
492 ASSERT (NewString
!= NULL
);
493 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
494 ASSERT_EFI_ERROR (Status
);
495 gBS
->FreePool (NewString
);
497 // created needed controller device item in first page
499 DevicePathHandleCount
= 0;
500 Status
= gBS
->LocateHandleBuffer (
502 &gEfiDevicePathProtocolGuid
,
504 &DevicePathHandleCount
,
505 &mDevicePathHandleBuffer
507 if (EFI_ERROR (Status
) || (DevicePathHandleCount
== 0)) {
511 for (Index
= 0; Index
< DevicePathHandleCount
; Index
++) {
512 if (FakeNvData
->PciDeviceFilter
== 0x01) {
514 // Only care PCI device which contain efi driver in its option rom.
518 // Check whether it is a pci device
520 ControllerDevicePath
= NULL
;
521 Status
= gBS
->OpenProtocol (
522 mDevicePathHandleBuffer
[Index
],
523 &gEfiPciIoProtocolGuid
,
527 EFI_OPEN_PROTOCOL_GET_PROTOCOL
529 if (EFI_ERROR (Status
)) {
533 // Check whether it contain efi driver in its option rom
535 Status
= gBS
->HandleProtocol(
536 mDevicePathHandleBuffer
[Index
],
537 &gEfiBusSpecificDriverOverrideProtocolGuid
,
538 (VOID
**) &BusSpecificDriverOverride
540 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
545 ControllerDevicePath
= NULL
;
546 Status
= gBS
->OpenProtocol (
547 mDevicePathHandleBuffer
[Index
],
548 &gEfiDevicePathProtocolGuid
,
549 (VOID
**) &ControllerDevicePath
,
552 EFI_OPEN_PROTOCOL_GET_PROTOCOL
554 ASSERT_EFI_ERROR (Status
);
556 // Save the device path protocol interface
558 mControllerDevicePathProtocol
[Index
] = ControllerDevicePath
;
561 // Get the driver name
563 ControllerName
= DevicePathToStr (ControllerDevicePath
);
566 // Export the driver name string and create item in set options page
568 Len
= StrSize (ControllerName
);
569 NewString
= AllocateZeroPool (Len
+ StrSize (L
"--"));
570 if (EFI_ERROR (CheckMapping (ControllerDevicePath
,NULL
, &mMappingDataBase
, NULL
, NULL
))) {
571 StrCat (NewString
, L
"--");
573 StrCat (NewString
, L
"**");
575 StrCat (NewString
, ControllerName
);
577 NewStringToken
= mControllerToken
[Index
];
578 if (NewStringToken
== 0) {
579 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
581 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
583 ASSERT_EFI_ERROR (Status
);
584 gBS
->FreePool (NewString
);
586 // Save the device path string toke for next access use
588 mControllerToken
[Index
] = NewStringToken
;
593 STRING_TOKEN (STR_GOTO_HELP_DRIVER
),
594 EFI_IFR_FLAG_CALLBACK
,
595 (UINT16
) (Index
+ KEY_VALUE_DEVICE_OFFSET
),
601 // Update first page form
604 Private
->RegisteredHandle
,
605 &mPlatformOverridesManagerGuid
,
612 gBS
->FreePool (UpdateData
.Data
);
617 Prepare to let user select the drivers which need mapping with the device controller
618 selected in first page.
620 @param Private Pointer to EFI_CALLBACK_INFO.
621 @param KeyValue The callback key value of device controller item in first page.
622 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
624 @retval EFI_SUCCESS Always returned.
628 UpdateBindingDriverSelectPage (
629 IN EFI_CALLBACK_INFO
*Private
,
631 IN PLAT_OVER_MNGR_DATA
*FakeNvData
634 EFI_HII_UPDATE_DATA UpdateData
;
639 EFI_STRING_ID NewStringToken
;
640 EFI_STRING_ID NewStringHelpToken
;
641 UINTN DriverImageHandleCount
;
643 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
644 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
646 BOOLEAN FreeDriverName
;
648 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
649 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
650 EFI_HANDLE DriverBindingHandle
;
652 // If user select a controller item in the first page the following code will be run.
653 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
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
656 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
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.
660 mCurrentPage
= FORM_ID_DRIVER
;
662 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
664 mSelectedCtrIndex
= KeyValue
- 0x100;
665 ASSERT (mSelectedCtrIndex
< MAX_CHOICE_NUM
);
666 mLastSavedDriverImageNum
= 0;
668 // Clear all the content in dynamic page
670 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
671 UpdateData
.Offset
= 0;
672 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
673 ASSERT (UpdateData
.Data
!= NULL
);
675 // Clear second page form
678 Private
->RegisteredHandle
,
679 &mPlatformOverridesManagerGuid
,
687 // Show all driver which support loaded image protocol in second page
689 DriverImageHandleCount
= 0;
690 Status
= gBS
->LocateHandleBuffer (
692 &gEfiLoadedImageProtocolGuid
,
694 &DriverImageHandleCount
,
695 &mDriverImageHandleBuffer
697 if (EFI_ERROR (Status
) || (DriverImageHandleCount
== 0)) {
698 return EFI_NOT_FOUND
;
701 mDriverImageHandleCount
= DriverImageHandleCount
;
702 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
704 // Step1: Get the driver image total file path for help string and the driver name.
708 // Find driver's Loaded Image protocol
712 Status
= gBS
->OpenProtocol (
713 mDriverImageHandleBuffer
[Index
],
714 &gEfiLoadedImageProtocolGuid
,
715 (VOID
**) &LoadedImage
,
718 EFI_OPEN_PROTOCOL_GET_PROTOCOL
720 if (EFI_ERROR (Status
)) {
721 FakeNvData
->DriSelection
[Index
] = 0x00;
724 mDriverImageProtocol
[Index
] = LoadedImage
;
726 // Find its related driver binding protocol
728 DriverBindingInterface
= NULL
;
729 DriverBindingHandle
= NULL
;
730 DriverBindingInterface
= GetBindingProtocolFromImageHandle (
731 mDriverImageHandleBuffer
[Index
],
734 if (DriverBindingInterface
== NULL
) {
735 FakeNvData
->DriSelection
[Index
] = 0x00;
740 // Get the EFI Loaded Image Device Path Protocol
742 LoadedImageDevicePath
= NULL
;
743 Status
= gBS
->HandleProtocol (
744 mDriverImageHandleBuffer
[Index
],
745 &gEfiLoadedImageDevicePathProtocolGuid
,
746 (VOID
**) &LoadedImageDevicePath
748 if (LoadedImageDevicePath
== NULL
) {
749 FakeNvData
->DriSelection
[Index
] = 0x00;
753 if (FakeNvData
->PciDeviceFilter
== 0x01) {
755 // only care the driver which is in a Pci device option rom,
756 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
758 if (!EFI_ERROR (Status
)) {
759 Status
= gBS
->HandleProtocol(
760 LoadedImage
->DeviceHandle
,
761 &gEfiBusSpecificDriverOverrideProtocolGuid
,
762 (VOID
**) &BusSpecificDriverOverride
764 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
765 FakeNvData
->DriSelection
[Index
] = 0x00;
769 FakeNvData
->DriSelection
[Index
] = 0x00;
775 // For driver name, try to get its component name, if fail, get its image name,
776 // if also fail, give a default name.
778 FreeDriverName
= FALSE
;
779 DriverName
= GetComponentName (DriverBindingHandle
);
780 if (DriverName
== NULL
) {
782 // get its image name
784 DriverName
= GetImageName (LoadedImage
);
786 if (DriverName
== NULL
) {
788 // give a default name
790 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME
), &DriverName
);
791 ASSERT (DriverName
!= NULL
);
792 FreeDriverName
= TRUE
; // the DriverName string need to free pool
797 // Step2 Export the driver name string and create check box item in second page
801 // First create the driver image name
803 NewString
= AllocateZeroPool (StrSize (DriverName
));
804 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol
[mSelectedCtrIndex
], LoadedImageDevicePath
, &mMappingDataBase
, NULL
, NULL
))) {
805 FakeNvData
->DriSelection
[Index
] = 0x00;
807 FakeNvData
->DriSelection
[Index
] = 0x01;
808 mLastSavedDriverImageNum
++;
810 StrCat (NewString
, DriverName
);
811 NewStringToken
= mDriverImageToken
[Index
];
812 if (NewStringToken
== 0) {
813 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
815 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
817 mDriverImageToken
[Index
] = NewStringToken
;
818 ASSERT_EFI_ERROR (Status
);
819 gBS
->FreePool (NewString
);
820 if (FreeDriverName
) {
821 gBS
->FreePool (DriverName
);
825 // Second create the driver image device path as item help string
827 DriverName
= DevicePathToStr (LoadedImageDevicePath
);
829 NewString
= AllocateZeroPool (StrSize (DriverName
));
830 StrCat (NewString
, DriverName
);
831 NewStringHelpToken
= mDriverImageFilePathToken
[Index
];
832 if (NewStringHelpToken
== 0) {
833 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringHelpToken
, NewString
);
835 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringHelpToken
, NewString
);
837 mDriverImageFilePathToken
[Index
] = NewStringHelpToken
;
838 ASSERT_EFI_ERROR (Status
);
839 gBS
->FreePool (NewString
);
840 gBS
->FreePool (DriverName
);
842 CreateCheckBoxOpCode (
843 (UINT16
) (DRIVER_SELECTION_QUESTION_ID
+ Index
),
844 VARSTORE_ID_PLAT_OVER_MNGR
,
845 (UINT16
) (DRIVER_SELECTION_VAR_OFFSET
+ Index
),
855 // Update second page form
858 Private
->RegisteredHandle
,
859 &mPlatformOverridesManagerGuid
,
866 gBS
->FreePool (UpdateData
.Data
);
871 Prepare to let user select the priority order of the drivers which are
872 selected in second page.
874 @param Private Pointer to EFI_CALLBACK_INFO.
875 @param KeyValue The callback key value of device controller item in first page.
876 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
878 @retval EFI_SUCCESS Always returned.
882 UpdatePrioritySelectPage (
883 IN EFI_CALLBACK_INFO
*Private
,
885 IN PLAT_OVER_MNGR_DATA
*FakeNvData
888 EFI_HII_UPDATE_DATA UpdateData
;
891 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
893 IFR_OPTION
*IfrOptionList
;
894 UINTN SelectedDriverImageNum
;
895 UINT32 DriverImageNO
;
901 // Following code will be run if user select 'order ... priority' item in second page
902 // Prepare third page. In third page, user will order the drivers priority which are selected in second page
904 mCurrentPage
= FORM_ID_ORDER
;
906 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
907 UpdateData
.Offset
= 0;
908 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
909 ASSERT (UpdateData
.Data
!= NULL
);
911 // Clear third page form
914 Private
->RegisteredHandle
,
915 &mPlatformOverridesManagerGuid
,
923 // Check how many drivers have been selected
925 SelectedDriverImageNum
= 0;
926 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
927 if (FakeNvData
->DriSelection
[Index
] != 0) {
928 SelectedDriverImageNum
++;
932 mSelectedDriverImageNum
= SelectedDriverImageNum
;
933 if (SelectedDriverImageNum
== 0) {
937 IfrOptionList
= AllocateZeroPool (0x200);
938 ASSERT_EFI_ERROR (IfrOptionList
!= NULL
);
940 // Create order list for those selected drivers
942 SelectedDriverImageNum
= 0;
943 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
944 if (FakeNvData
->DriSelection
[Index
] != 0) {
945 IfrOptionList
[SelectedDriverImageNum
].StringToken
= mDriverImageToken
[Index
];
947 // Use the NO. in driver binding buffer as value, will use it later
949 IfrOptionList
[SelectedDriverImageNum
].Value
.u8
= (UINT8
) (Index
+ 1);
950 IfrOptionList
[SelectedDriverImageNum
].Flags
= 0;
953 // Get the EFI Loaded Image Device Path Protocol
955 LoadedImageDevicePath
= NULL
;
956 gBS
->HandleProtocol (
957 mDriverImageHandleBuffer
[Index
],
958 &gEfiLoadedImageDevicePathProtocolGuid
,
959 (VOID
**) &LoadedImageDevicePath
961 ASSERT (LoadedImageDevicePath
!= NULL
);
964 // Check the driver DriverImage's order number in mapping database
968 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
969 LoadedImageDevicePath
,
974 if (DriverImageNO
== 0) {
975 DriverImageNO
= (UINT32
) mLastSavedDriverImageNum
+ 1;
976 mLastSavedDriverImageNum
++;
978 TempNO
[SelectedDriverImageNum
] = DriverImageNO
;
979 SelectedDriverImageNum
++;
983 ASSERT (SelectedDriverImageNum
== mSelectedDriverImageNum
);
985 // NvRamMap Must be clear firstly
987 ZeroMem (FakeNvData
->DriOrder
, 100);
990 // Order the selected drivers according to the info already in mapping database
991 // the less order number in mapping database the less order number in NvRamMap
993 for (Index
=0; Index
< SelectedDriverImageNum
; Index
++) {
995 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
998 for (Index1
=0; Index1
< SelectedDriverImageNum
; Index1
++) {
999 if (TempNO
[Index1
] < TempNO
[MinNO
]) {
1004 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
1006 FakeNvData
->DriOrder
[Index
] =IfrOptionList
[MinNO
].Value
.u8
;
1007 TempNO
[MinNO
] = 101;
1010 CreateOrderedListOpCode (
1011 (UINT16
) DRIVER_ORDER_QUESTION_ID
,
1012 VARSTORE_ID_PLAT_OVER_MNGR
,
1013 (UINT16
) DRIVER_ORDER_VAR_OFFSET
,
1014 mControllerToken
[mSelectedCtrIndex
],
1015 mControllerToken
[mSelectedCtrIndex
],
1016 EFI_IFR_FLAG_RESET_REQUIRED
,
1018 EFI_IFR_NUMERIC_SIZE_1
,
1021 SelectedDriverImageNum
,
1026 // Update third page form
1029 Private
->RegisteredHandle
,
1030 &mPlatformOverridesManagerGuid
,
1037 gBS
->FreePool (IfrOptionList
);
1038 gBS
->FreePool (UpdateData
.Data
);
1043 Save the save the mapping database to NV variable.
1045 @param Private Pointer to EFI_CALLBACK_INFO.
1046 @param KeyValue The callback key value of device controller item in first page.
1047 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
1049 @retval EFI_SUCCESS Always returned.
1054 IN EFI_CALLBACK_INFO
*Private
,
1056 IN PLAT_OVER_MNGR_DATA
*FakeNvData
1061 UINTN SelectedDriverImageNum
;
1062 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1064 // Following code will be run if user select 'commint changes' in third page
1065 // user enter 'Commit Changes' to save the mapping database
1067 DeleteDriverImage (mControllerDevicePathProtocol
[mSelectedCtrIndex
], NULL
, &mMappingDataBase
);
1068 for (SelectedDriverImageNum
= 0; SelectedDriverImageNum
< mSelectedDriverImageNum
; SelectedDriverImageNum
++) {
1070 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
1072 Index
= FakeNvData
->DriOrder
[SelectedDriverImageNum
] - 1;
1075 // Get the EFI Loaded Image Device Path Protocol
1077 LoadedImageDevicePath
= NULL
;
1078 Status
= gBS
->HandleProtocol (
1079 mDriverImageHandleBuffer
[Index
],
1080 &gEfiLoadedImageDevicePathProtocolGuid
,
1081 (VOID
**) &LoadedImageDevicePath
1083 ASSERT (LoadedImageDevicePath
!= NULL
);
1086 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
1087 LoadedImageDevicePath
,
1089 (UINT32
)SelectedDriverImageNum
+ 1
1092 Status
= SaveOverridesMapping (&mMappingDataBase
);
1098 This function allows a caller to extract the current configuration for one
1099 or more named elements from the target driver.
1101 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1102 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1103 @param Progress On return, points to a character in the Request string.
1104 Points to the string's null terminator if request was successful.
1105 Points to the most recent '&' before the first failing name/value
1106 pair (or the beginning of the string if the failure is in the
1107 first name/value pair) if the request was not successful.
1108 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
1109 has all values filled in for the names in the Request string.
1110 String to be allocated by the called function.
1112 @retval EFI_SUCCESS The Results is filled with the requested values.
1113 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
1114 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
1115 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1120 PlatOverMngrExtractConfig (
1121 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1122 IN CONST EFI_STRING Request
,
1123 OUT EFI_STRING
*Progress
,
1124 OUT EFI_STRING
*Results
1128 EFI_CALLBACK_INFO
*Private
;
1129 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1131 if (Request
== NULL
) {
1132 return EFI_NOT_FOUND
;
1135 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1136 HiiConfigRouting
= Private
->HiiConfigRouting
;
1139 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1141 Status
= HiiConfigRouting
->BlockToConfig (
1144 (UINT8
*) &Private
->FakeNvData
,
1145 sizeof (PLAT_OVER_MNGR_DATA
),
1153 This function processes the results of changes in configuration.
1155 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1156 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1157 @param Progress A pointer to a string filled in with the offset of the most
1158 recent '&' before the first failing name/value pair (or the
1159 beginning of the string if the failure is in the first
1160 name/value pair) or the terminating NULL if all was successful.
1162 @retval EFI_SUCCESS The Results is processed successfully.
1163 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1164 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1169 PlatOverMngrRouteConfig (
1170 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1171 IN CONST EFI_STRING Configuration
,
1172 OUT EFI_STRING
*Progress
1175 EFI_CALLBACK_INFO
*Private
;
1179 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1181 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1183 FakeNvData
= &Private
->FakeNvData
;
1184 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1185 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1186 if (EFI_ERROR (Status
)) {
1190 if (mCurrentPage
== FORM_ID_DRIVER
) {
1191 KeyValue
= KEY_VALUE_DRIVER_GOTO_ORDER
;
1192 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1193 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1194 CommintChanges (Private
, KeyValue
, FakeNvData
);
1196 // Since UpdatePrioritySelectPage will change mCurrentPage,
1197 // should ensure the mCurrentPage still indicate the second page here
1199 mCurrentPage
= FORM_ID_DRIVER
;
1202 if (mCurrentPage
== FORM_ID_ORDER
) {
1203 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1204 CommintChanges (Private
, KeyValue
, FakeNvData
);
1210 This is the function that is called to provide results data to the driver. This data
1211 consists of a unique key which is used to identify what data is either being passed back
1214 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1215 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1216 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1217 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1218 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1219 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1220 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1221 KeyValue == 0x1800 : user select 'commint changes' in third page
1222 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1223 @param Type The type of value for the question.
1224 @param Value A pointer to the data being sent to the original exporting driver.
1225 @param ActionRequest On return, points to the action requested by the callback function.
1227 @retval EFI_SUCCESS Always returned.
1232 PlatOverMngrCallback (
1233 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1234 IN EFI_BROWSER_ACTION Action
,
1235 IN EFI_QUESTION_ID KeyValue
,
1237 IN EFI_IFR_TYPE_VALUE
*Value
,
1238 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1241 EFI_CALLBACK_INFO
*Private
;
1243 EFI_STRING_ID NewStringToken
;
1245 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1248 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1250 FakeNvData
= &Private
->FakeNvData
;
1251 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1252 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1253 if (EFI_ERROR (Status
)) {
1257 if (KeyValue
== KEY_VALUE_DEVICE_REFRESH
||
1258 KeyValue
== KEY_VALUE_DEVICE_FILTER
||
1259 KeyValue
== KEY_VALUE_DRIVER_GOTO_PREVIOUS
1261 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1263 // Update page title string
1265 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1266 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"First, Select the controller by device path");
1267 ASSERT_EFI_ERROR (Status
);
1270 if (((KEY_VALUE_DEVICE_OFFSET
<= KeyValue
) && (KeyValue
< KEY_VALUE_DEVICE_MAX
)) || (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
)) {
1271 if (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
) {
1272 KeyValue
= (EFI_QUESTION_ID
) (mSelectedCtrIndex
+ 0x100);
1274 UpdateBindingDriverSelectPage (Private
, KeyValue
, FakeNvData
);
1276 // Update page title string
1278 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1279 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Second, Select drivers for the previous selected controller");
1280 ASSERT_EFI_ERROR (Status
);
1283 if (KeyValue
== KEY_VALUE_DRIVER_GOTO_ORDER
) {
1284 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1286 // Update page title string
1288 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1289 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Finally, Set the priority order for the drivers and save them");
1290 ASSERT_EFI_ERROR (Status
);
1293 if (KeyValue
== KEY_VALUE_ORDER_SAVE_AND_EXIT
) {
1294 Status
= CommintChanges (Private
, KeyValue
, FakeNvData
);
1295 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1296 if (EFI_ERROR (Status
)) {
1297 IfrLibCreatePopUp (1, &Key
, L
"Single Override Info too large, Saving Error!");
1298 return EFI_DEVICE_ERROR
;
1302 if (KeyValue
== KEY_VALUE_DEVICE_CLEAR
) {
1304 // Deletes all environment variable(s) that contain the override mappings info
1306 FreeMappingDatabase (&mMappingDataBase
);
1307 Status
= SaveOverridesMapping (&mMappingDataBase
);
1308 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1311 // Pass changed uncommitted data back to Form Browser
1313 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1314 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) FakeNvData
, NULL
);
1320 Function unpacks a device path data structure so that all the nodes
1321 of a device path are naturally aligned.
1323 @param DevPath A pointer to a device path data structure
1325 @return If the memory for the device path is successfully allocated, then a
1326 @return pointer to the new device path is returned. Otherwise, NULL is returned.
1329 EFI_DEVICE_PATH_PROTOCOL
*
1331 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1334 EFI_DEVICE_PATH_PROTOCOL
*Src
;
1335 EFI_DEVICE_PATH_PROTOCOL
*Dest
;
1336 EFI_DEVICE_PATH_PROTOCOL
*NewPath
;
1340 // Walk device path and round sizes to valid boundries
1345 Size
+= DevicePathNodeLength (Src
);
1346 Size
+= ALIGN_SIZE (Size
);
1348 if (IsDevicePathEnd (Src
)) {
1352 Src
= NextDevicePathNode (Src
);
1355 // Allocate space for the unpacked path
1357 NewPath
= AllocateZeroPool (Size
);
1360 ASSERT (((UINTN
) NewPath
) % MIN_ALIGNMENT_SIZE
== 0);
1368 Size
= DevicePathNodeLength (Src
);
1369 CopyMem (Dest
, Src
, Size
);
1370 Size
+= ALIGN_SIZE (Size
);
1371 SetDevicePathNodeLength (Dest
, Size
);
1372 Dest
->Type
|= EFI_DP_TYPE_UNPACKED
;
1373 Dest
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) Dest
) + Size
);
1375 if (IsDevicePathEnd (Src
)) {
1379 Src
= NextDevicePathNode (Src
);
1388 Get the description string by device path.
1390 @param DevPath The input device path.
1392 @retval !NULL The description string retured.
1393 @retval NULL The description string cannot be found.
1398 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1403 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
1405 if (DevPath
== NULL
) {
1409 Status
= gBS
->LocateProtocol (
1410 &gEfiDevicePathToTextProtocolGuid
,
1412 (VOID
**) &DevPathToText
1414 if (!EFI_ERROR (Status
)) {
1415 ToText
= DevPathToText
->ConvertDevicePathToText (
1420 ASSERT (ToText
!= NULL
);