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
*));
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 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1132 HiiConfigRouting
= Private
->HiiConfigRouting
;
1135 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1137 Status
= HiiConfigRouting
->BlockToConfig (
1140 (UINT8
*) &Private
->FakeNvData
,
1141 sizeof (PLAT_OVER_MNGR_DATA
),
1149 This function processes the results of changes in configuration.
1151 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1152 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1153 @param Progress A pointer to a string filled in with the offset of the most
1154 recent '&' before the first failing name/value pair (or the
1155 beginning of the string if the failure is in the first
1156 name/value pair) or the terminating NULL if all was successful.
1158 @retval EFI_SUCCESS The Results is processed successfully.
1159 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1160 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1165 PlatOverMngrRouteConfig (
1166 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1167 IN CONST EFI_STRING Configuration
,
1168 OUT EFI_STRING
*Progress
1171 EFI_CALLBACK_INFO
*Private
;
1175 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1177 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1179 FakeNvData
= &Private
->FakeNvData
;
1180 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1181 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1182 if (EFI_ERROR (Status
)) {
1186 if (mCurrentPage
== FORM_ID_DRIVER
) {
1187 KeyValue
= KEY_VALUE_DRIVER_GOTO_ORDER
;
1188 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1189 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1190 CommintChanges (Private
, KeyValue
, FakeNvData
);
1192 // Since UpdatePrioritySelectPage will change mCurrentPage,
1193 // should ensure the mCurrentPage still indicate the second page here
1195 mCurrentPage
= FORM_ID_DRIVER
;
1198 if (mCurrentPage
== FORM_ID_ORDER
) {
1199 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1200 CommintChanges (Private
, KeyValue
, FakeNvData
);
1206 This is the function that is called to provide results data to the driver. This data
1207 consists of a unique key which is used to identify what data is either being passed back
1210 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1211 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1212 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1213 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1214 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1215 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1216 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1217 KeyValue == 0x1800 : user select 'commint changes' in third page
1218 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1219 @param Type The type of value for the question.
1220 @param Value A pointer to the data being sent to the original exporting driver.
1221 @param ActionRequest On return, points to the action requested by the callback function.
1223 @retval EFI_SUCCESS Always returned.
1228 PlatOverMngrCallback (
1229 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1230 IN EFI_BROWSER_ACTION Action
,
1231 IN EFI_QUESTION_ID KeyValue
,
1233 IN EFI_IFR_TYPE_VALUE
*Value
,
1234 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1237 EFI_CALLBACK_INFO
*Private
;
1239 EFI_STRING_ID NewStringToken
;
1241 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1244 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1246 FakeNvData
= &Private
->FakeNvData
;
1247 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1248 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1249 if (EFI_ERROR (Status
)) {
1253 if (KeyValue
== KEY_VALUE_DEVICE_REFRESH
||
1254 KeyValue
== KEY_VALUE_DEVICE_FILTER
||
1255 KeyValue
== KEY_VALUE_DRIVER_GOTO_PREVIOUS
1257 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1259 // Update page title string
1261 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1262 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"First, Select the controller by device path");
1263 ASSERT_EFI_ERROR (Status
);
1266 if (((KEY_VALUE_DEVICE_OFFSET
<= KeyValue
) && (KeyValue
< KEY_VALUE_DEVICE_MAX
)) || (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
)) {
1267 if (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
) {
1268 KeyValue
= (EFI_QUESTION_ID
) (mSelectedCtrIndex
+ 0x100);
1270 UpdateBindingDriverSelectPage (Private
, KeyValue
, FakeNvData
);
1272 // Update page title string
1274 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1275 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Second, Select drivers for the previous selected controller");
1276 ASSERT_EFI_ERROR (Status
);
1279 if (KeyValue
== KEY_VALUE_DRIVER_GOTO_ORDER
) {
1280 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1282 // Update page title string
1284 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1285 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Finally, Set the priority order for the drivers and save them");
1286 ASSERT_EFI_ERROR (Status
);
1289 if (KeyValue
== KEY_VALUE_ORDER_SAVE_AND_EXIT
) {
1290 Status
= CommintChanges (Private
, KeyValue
, FakeNvData
);
1291 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1292 if (EFI_ERROR (Status
)) {
1293 IfrLibCreatePopUp (1, &Key
, L
"Single Override Info too large, Saving Error!");
1294 return EFI_DEVICE_ERROR
;
1298 if (KeyValue
== KEY_VALUE_DEVICE_CLEAR
) {
1300 // Deletes all environment variable(s) that contain the override mappings info
1302 FreeMappingDatabase (&mMappingDataBase
);
1303 Status
= SaveOverridesMapping (&mMappingDataBase
);
1304 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1307 // Pass changed uncommitted data back to Form Browser
1309 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1310 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) FakeNvData
, NULL
);
1316 Function unpacks a device path data structure so that all the nodes
1317 of a device path are naturally aligned.
1319 @param DevPath A pointer to a device path data structure
1321 @return If the memory for the device path is successfully allocated, then a
1322 @return pointer to the new device path is returned. Otherwise, NULL is returned.
1325 EFI_DEVICE_PATH_PROTOCOL
*
1327 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1330 EFI_DEVICE_PATH_PROTOCOL
*Src
;
1331 EFI_DEVICE_PATH_PROTOCOL
*Dest
;
1332 EFI_DEVICE_PATH_PROTOCOL
*NewPath
;
1336 // Walk device path and round sizes to valid boundries
1341 Size
+= DevicePathNodeLength (Src
);
1342 Size
+= ALIGN_SIZE (Size
);
1344 if (IsDevicePathEnd (Src
)) {
1348 Src
= NextDevicePathNode (Src
);
1351 // Allocate space for the unpacked path
1353 NewPath
= AllocateZeroPool (Size
);
1356 ASSERT (((UINTN
) NewPath
) % MIN_ALIGNMENT_SIZE
== 0);
1364 Size
= DevicePathNodeLength (Src
);
1365 CopyMem (Dest
, Src
, Size
);
1366 Size
+= ALIGN_SIZE (Size
);
1367 SetDevicePathNodeLength (Dest
, Size
);
1368 Dest
->Type
|= EFI_DP_TYPE_UNPACKED
;
1369 Dest
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) Dest
) + Size
);
1371 if (IsDevicePathEnd (Src
)) {
1375 Src
= NextDevicePathNode (Src
);
1384 Get the description string by device path.
1386 @param DevPath The input device path.
1388 @retval !NULL The description string retured.
1389 @retval NULL The description string cannot be found.
1394 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1399 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
1401 if (DevPath
== NULL
) {
1405 Status
= gBS
->LocateProtocol (
1406 &gEfiDevicePathToTextProtocolGuid
,
1408 (VOID
**) &DevPathToText
1410 if (!EFI_ERROR (Status
)) {
1411 ToText
= DevPathToText
->ConvertDevicePathToText (
1416 ASSERT (ToText
!= NULL
);