3 A UI application to offer a UI interface in device manager to let user configure
4 platform override protocol to override the default algorithm for matching
5 drivers to controllers.
8 1. The UI application dynamicly locate all controller device path.
9 2. The UI application dynamicly locate all drivers which support binding protocol.
10 3. The UI application export and dynamicly update two menu to let user select the
11 mapping between drivers to controllers.
12 4. The UI application save all the mapping info in NV variables which will be consumed
13 by platform override protocol driver to publish the platform override protocol.
15 Copyright (c) 2007 - 2008, Intel Corporation
16 All rights reserved. This program and the accompanying materials
17 are licensed and made available under the terms and conditions of the BSD License
18 which accompanies this distribution. The full text of the license may be found at
19 http://opensource.org/licenses/bsd-license.php
21 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
22 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
28 #include <Protocol/HiiConfigAccess.h>
29 #include <Protocol/HiiConfigRouting.h>
30 #include <Protocol/HiiDatabase.h>
31 #include <Protocol/FormBrowser2.h>
32 #include <Protocol/LoadedImage.h>
33 #include <Protocol/FirmwareVolume2.h>
34 #include <Protocol/PciIo.h>
35 #include <Protocol/BusSpecificDriverOverride.h>
36 #include <Protocol/ComponentName2.h>
37 #include <Protocol/ComponentName.h>
38 #include <Protocol/DriverBinding.h>
39 #include <Protocol/DevicePathToText.h>
40 #include <Guid/GlobalVariable.h>
42 #include <Library/BaseLib.h>
43 #include <Library/DebugLib.h>
44 #include <Library/UefiLib.h>
45 #include <Library/UefiApplicationEntryPoint.h>
46 #include <Library/UefiBootServicesTableLib.h>
47 #include <Library/PlatformDriverOverrideLib.h>
48 #include <Library/HiiLib.h>
49 #include <Library/IfrSupportLib.h>
50 #include <Library/ExtendedHiiLib.h>
51 #include <Library/ExtendedIfrSupportLib.h>
52 #include <Library/BaseMemoryLib.h>
53 #include <Library/MemoryAllocationLib.h>
54 #include <Library/UefiRuntimeServicesTableLib.h>
55 #include <Library/DevicePathLib.h>
56 #include "PlatOverMngr.h"
58 #define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k')
59 #define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE)
63 EFI_HANDLE DriverHandle
;
64 EFI_HII_HANDLE RegisteredHandle
;
65 PLAT_OVER_MNGR_DATA FakeNvData
;
66 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
67 EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess
;
71 // uni string and Vfr Binary data.
73 extern UINT8 VfrBin
[];
74 extern UINT8 PlatOverMngrStrings
[];
79 EFI_GUID mPlatformOverridesManagerGuid
= PLAT_OVER_MNGR_GUID
;
80 LIST_ENTRY mMappingDataBase
= INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase
);
82 EFI_HANDLE
*mDevicePathHandleBuffer
;
83 EFI_HANDLE
*mDriverImageHandleBuffer
;
85 INTN mSelectedCtrIndex
;
86 EFI_STRING_ID mControllerToken
[MAX_CHOICE_NUM
];
87 UINTN mDriverImageHandleCount
;
88 EFI_STRING_ID mDriverImageToken
[MAX_CHOICE_NUM
];
89 EFI_STRING_ID mDriverImageFilePathToken
[MAX_CHOICE_NUM
];
90 EFI_LOADED_IMAGE_PROTOCOL
*mDriverImageProtocol
[MAX_CHOICE_NUM
];
91 EFI_DEVICE_PATH_PROTOCOL
*mControllerDevicePathProtocol
[MAX_CHOICE_NUM
];
92 UINTN mSelectedDriverImageNum
;
93 UINTN mLastSavedDriverImageNum
;
94 CHAR8 mLanguage
[RFC_3066_ENTRY_SIZE
];
98 Converting a given device to an unicode string.
100 This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol
101 does not installed, then return unknown device path L"?" directly.
103 @param DevPath Given device path instance
105 @return Converted string from given device path.
106 @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.
110 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
114 Do string convertion for the ComponentName supported language. It do
115 the convertion just for english language code from RFC 3066 to ISO 639-2.
116 Then it will check whether the converted language is in the supported language list.
117 If not supported, NULL is returned.
118 If Language is not english, NULL is returned.
120 @param SupportedLanguages Pointer to ComponentName supported language string list. ISO 639-2 language
121 @param Language The language string. RFC 3066 language
123 @return English language string (ISO 639-2)
124 @return NULL if the conertion is not successful.
128 ConvertComponentNameSupportLanguage (
129 IN CHAR8
*SupportedLanguages
,
137 // Check the input language is English
139 if (AsciiStrnCmp (Language
, "en-", 3) != 0) {
144 // Check SupportedLanguages format
146 if (AsciiStrStr (SupportedLanguages
, "en-") != NULL
) {
148 // Create RFC 3066 language
150 LangCode
= AllocateZeroPool(AsciiStrSize (Language
));
151 AsciiStrCpy (LangCode
, Language
);
152 } else if (AsciiStrStr (SupportedLanguages
, "en") != NULL
) {
154 // Create ISO 639-2 Language
156 LangCode
= AllocateZeroPool(4);
157 AsciiStrCpy (LangCode
, "eng");
164 Get the driver name by ComponentName or ComponentName2 protocol
165 according to the driver binding handle
167 @param DriverBindingHandle The Handle of DriverBinding.
169 @retval !NULL Pointer into the image name if the image name is found,
170 @retval NULL Pointer to NULL if the image name is not found.
175 IN EFI_HANDLE DriverBindingHandle
179 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
180 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
181 CHAR8
*SupportedLanguage
;
184 ComponentName
= NULL
;
185 ComponentName2
= NULL
;
186 Status
= gBS
->OpenProtocol (
188 &gEfiComponentName2ProtocolGuid
,
189 (VOID
**) &ComponentName2
,
192 EFI_OPEN_PROTOCOL_GET_PROTOCOL
194 if (EFI_ERROR(Status
)) {
195 Status
= gBS
->OpenProtocol (
197 &gEfiComponentNameProtocolGuid
,
198 (VOID
**) &ComponentName
,
201 EFI_OPEN_PROTOCOL_GET_PROTOCOL
205 Status
= EFI_SUCCESS
;
207 if (ComponentName
!= NULL
) {
208 if (ComponentName
->GetDriverName
!= NULL
) {
209 SupportedLanguage
= ConvertComponentNameSupportLanguage (ComponentName
->SupportedLanguages
, mLanguage
);
210 if (SupportedLanguage
!= NULL
) {
211 Status
= ComponentName
->GetDriverName (
216 FreePool (SupportedLanguage
);
219 } else if (ComponentName2
!= NULL
) {
220 if (ComponentName2
->GetDriverName
!= NULL
) {
221 Status
= ComponentName2
->GetDriverName (
229 if (EFI_ERROR (Status
)) {
237 Get the image name from EFI UI section.
238 Get FV protocol by its loaded image protoocl to abastract EFI UI section.
240 @param Image Pointer to the loaded image protocol
242 @retval !NULL Pointer to the image name if the image name is found,
243 @retval NULL NULL if the image name is not found.
248 IN EFI_LOADED_IMAGE_PROTOCOL
*Image
252 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
253 EFI_DEVICE_PATH_PROTOCOL
*AlignedDevPathNode
;
254 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
257 UINT32 AuthenticationStatus
;
259 EFI_FIRMWARE_VOLUME2_PROTOCOL
*Fv2
;
265 if (Image
->FilePath
== NULL
) {
268 DevPathNode
= Image
->FilePath
;
270 while (!IsDevicePathEnd (DevPathNode
)) {
272 // Make sure device path node is aligned when accessing it's FV Name Guid field.
274 AlignedDevPathNode
= AllocateCopyPool (DevicePathNodeLength(DevPathNode
), DevPathNode
);
277 // Find the Fv File path
279 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)AlignedDevPathNode
);
280 if (NameGuid
!= NULL
) {
281 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) AlignedDevPathNode
;
282 Status
= gBS
->HandleProtocol (
284 &gEfiFirmwareVolume2ProtocolGuid
,
288 // Locate Image EFI UI section to get the image name.
290 if (!EFI_ERROR (Status
)) {
291 Status
= Fv2
->ReadSection (
293 &FvFilePath
->FvFileName
,
294 EFI_SECTION_USER_INTERFACE
,
298 &AuthenticationStatus
300 if (!EFI_ERROR (Status
)) {
301 FreePool (AlignedDevPathNode
);
308 FreePool (AlignedDevPathNode
);
311 // Next device path node
313 DevPathNode
= NextDevicePathNode (DevPathNode
);
320 Prepare the first page to let user select the device controller which need to
321 add mapping drivers if user select 'Refresh' in first page.
322 During first page, user will see all currnet controller device path in system,
323 select any device path will go to second page to select its overrides drivers.
325 @param Private Pointer to EFI_CALLBACK_INFO.
326 @param KeyValue The callback key value of device controller item in first page.
327 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
329 @retval EFI_SUCCESS Always returned.
333 UpdateDeviceSelectPage (
334 IN EFI_CALLBACK_INFO
*Private
,
336 IN PLAT_OVER_MNGR_DATA
*FakeNvData
339 EFI_HII_UPDATE_DATA UpdateData
;
343 UINTN DevicePathHandleCount
;
345 EFI_STRING_ID NewStringToken
;
346 CHAR16
*ControllerName
;
347 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
348 EFI_PCI_IO_PROTOCOL
*PciIo
;
349 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
353 // set current page form ID.
355 mCurrentPage
= FORM_ID_DEVICE
;
358 // Get Platform supported Language (RFC_3066 format)
360 LangSize
= RFC_3066_ENTRY_SIZE
;
361 Status
= gRT
->GetVariable (
363 &gEfiGlobalVariableGuid
,
368 ASSERT_EFI_ERROR (Status
);
371 // Initial the mapping database in memory
373 FreeMappingDatabase (&mMappingDataBase
);
374 Status
= InitOverridesMapping (&mMappingDataBase
);
377 // Clear all the content in the first page
379 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
380 UpdateData
.Offset
= 0;
381 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
382 ASSERT (UpdateData
.Data
!= NULL
);
384 // Clear first page form
387 Private
->RegisteredHandle
,
388 &mPlatformOverridesManagerGuid
,
396 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
397 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
399 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH
);
400 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH
), &NewString
);
401 ASSERT (NewString
!= NULL
);
402 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
403 ASSERT_EFI_ERROR (Status
);
404 FreePool (NewString
);
406 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH_HELP
);
407 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH_HELP
), &NewString
);
408 ASSERT (NewString
!= NULL
);
409 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
410 ASSERT_EFI_ERROR (Status
);
411 FreePool (NewString
);
414 // created needed controller device item in first page
416 DevicePathHandleCount
= 0;
417 Status
= gBS
->LocateHandleBuffer (
419 &gEfiDevicePathProtocolGuid
,
421 &DevicePathHandleCount
,
422 &mDevicePathHandleBuffer
424 if (EFI_ERROR (Status
) || (DevicePathHandleCount
== 0)) {
428 for (Index
= 0; Index
< DevicePathHandleCount
; Index
++) {
429 if (FakeNvData
->PciDeviceFilter
== 0x01) {
431 // Only care PCI device which contain efi driver in its option rom.
435 // Check whether it is a pci device
437 ControllerDevicePath
= NULL
;
438 Status
= gBS
->OpenProtocol (
439 mDevicePathHandleBuffer
[Index
],
440 &gEfiPciIoProtocolGuid
,
444 EFI_OPEN_PROTOCOL_GET_PROTOCOL
446 if (EFI_ERROR (Status
)) {
450 // Check whether it contain efi driver in its option rom
452 Status
= gBS
->HandleProtocol(
453 mDevicePathHandleBuffer
[Index
],
454 &gEfiBusSpecificDriverOverrideProtocolGuid
,
455 (VOID
**) &BusSpecificDriverOverride
457 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
462 ControllerDevicePath
= NULL
;
463 Status
= gBS
->OpenProtocol (
464 mDevicePathHandleBuffer
[Index
],
465 &gEfiDevicePathProtocolGuid
,
466 (VOID
**) &ControllerDevicePath
,
469 EFI_OPEN_PROTOCOL_GET_PROTOCOL
471 ASSERT_EFI_ERROR (Status
);
473 // Save the device path protocol interface
475 mControllerDevicePathProtocol
[Index
] = ControllerDevicePath
;
478 // Get the driver name
480 ControllerName
= DevicePathToStr (ControllerDevicePath
);
483 // Export the driver name string and create item in set options page
485 Len
= StrSize (ControllerName
);
486 NewString
= AllocateZeroPool (Len
+ StrSize (L
"--"));
487 ASSERT (NewString
!= NULL
);
488 if (EFI_ERROR (CheckMapping (ControllerDevicePath
,NULL
, &mMappingDataBase
, NULL
, NULL
))) {
489 StrCat (NewString
, L
"--");
491 StrCat (NewString
, L
"**");
493 StrCat (NewString
, ControllerName
);
495 NewStringToken
= mControllerToken
[Index
];
496 if (NewStringToken
== 0) {
497 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
499 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
501 ASSERT_EFI_ERROR (Status
);
502 FreePool (NewString
);
504 // Save the device path string toke for next access use
506 mControllerToken
[Index
] = NewStringToken
;
511 STRING_TOKEN (STR_GOTO_HELP_DRIVER
),
512 EFI_IFR_FLAG_CALLBACK
,
513 (UINT16
) (Index
+ KEY_VALUE_DEVICE_OFFSET
),
519 // Update first page form
522 Private
->RegisteredHandle
,
523 &mPlatformOverridesManagerGuid
,
530 FreePool (UpdateData
.Data
);
535 Get the first Driver Binding handle which has the specific image handle.
537 @param ImageHandle The Image handle
539 @return Handle to Driver binding
540 @retval NULL The paramter is not valid or the driver binding handle is not found.
544 GetDriverBindingHandleFromImageHandle (
545 IN EFI_HANDLE ImageHandle
550 UINTN DriverBindingHandleCount
;
551 EFI_HANDLE
*DriverBindingHandleBuffer
;
552 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
553 EFI_HANDLE DriverBindingHandle
;
555 DriverBindingHandle
= NULL
;
557 if (ImageHandle
== NULL
) {
561 // Get all drivers which support driver binding protocol
563 DriverBindingHandleCount
= 0;
564 Status
= gBS
->LocateHandleBuffer (
566 &gEfiDriverBindingProtocolGuid
,
568 &DriverBindingHandleCount
,
569 &DriverBindingHandleBuffer
571 if (EFI_ERROR (Status
) || (DriverBindingHandleCount
== 0)) {
576 // Get the first Driver Binding handle which has the specific image handle.
578 for (Index
= 0; Index
< DriverBindingHandleCount
; Index
++) {
579 DriverBindingInterface
= NULL
;
580 Status
= gBS
->OpenProtocol (
581 DriverBindingHandleBuffer
[Index
],
582 &gEfiDriverBindingProtocolGuid
,
583 (VOID
**) &DriverBindingInterface
,
586 EFI_OPEN_PROTOCOL_GET_PROTOCOL
588 if (EFI_ERROR (Status
)) {
592 if (DriverBindingInterface
->ImageHandle
== ImageHandle
) {
593 DriverBindingHandle
= DriverBindingHandleBuffer
[Index
];
598 FreePool (DriverBindingHandleBuffer
);
599 return DriverBindingHandle
;
603 Prepare to let user select the drivers which need mapping with the device controller
604 selected in first page.
606 @param Private Pointer to EFI_CALLBACK_INFO.
607 @param KeyValue The callback key value of device controller item in first page.
608 KeyValue is larger than or equal to KEY_VALUE_DEVICE_OFFSET.
609 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
611 @retval EFI_SUCCESS Always returned.
615 UpdateBindingDriverSelectPage (
616 IN EFI_CALLBACK_INFO
*Private
,
618 IN PLAT_OVER_MNGR_DATA
*FakeNvData
621 EFI_HII_UPDATE_DATA UpdateData
;
625 EFI_STRING_ID NewStringToken
;
626 EFI_STRING_ID NewStringHelpToken
;
627 UINTN DriverImageHandleCount
;
628 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
630 BOOLEAN FreeDriverName
;
631 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
632 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
633 EFI_HANDLE DriverBindingHandle
;
636 // If user select a controller item in the first page the following code will be run.
637 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
639 //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols
640 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
641 // 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.
644 mCurrentPage
= FORM_ID_DRIVER
;
646 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
648 mSelectedCtrIndex
= KeyValue
- KEY_VALUE_DEVICE_OFFSET
;
649 ASSERT (mSelectedCtrIndex
> 0 && mSelectedCtrIndex
< MAX_CHOICE_NUM
);
651 mLastSavedDriverImageNum
= 0;
653 // Clear all the content in dynamic page
655 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
656 UpdateData
.Offset
= 0;
657 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
658 ASSERT (UpdateData
.Data
!= NULL
);
660 // Clear second page form
663 Private
->RegisteredHandle
,
664 &mPlatformOverridesManagerGuid
,
672 // Show all driver which support loaded image protocol in second page
674 DriverImageHandleCount
= 0;
675 Status
= gBS
->LocateHandleBuffer (
677 &gEfiLoadedImageProtocolGuid
,
679 &DriverImageHandleCount
,
680 &mDriverImageHandleBuffer
682 if (EFI_ERROR (Status
) || (DriverImageHandleCount
== 0)) {
683 return EFI_NOT_FOUND
;
686 mDriverImageHandleCount
= DriverImageHandleCount
;
687 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
689 // Step1: Get the driver image total file path for help string and the driver name.
693 // Find driver's Loaded Image protocol
697 Status
= gBS
->OpenProtocol (
698 mDriverImageHandleBuffer
[Index
],
699 &gEfiLoadedImageProtocolGuid
,
700 (VOID
**) &LoadedImage
,
703 EFI_OPEN_PROTOCOL_GET_PROTOCOL
705 if (EFI_ERROR (Status
)) {
706 FakeNvData
->DriSelection
[Index
] = 0x00;
709 mDriverImageProtocol
[Index
] = LoadedImage
;
711 // Find its related driver binding protocol
713 DriverBindingHandle
= GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer
[Index
]);
714 if (DriverBindingHandle
== NULL
) {
715 FakeNvData
->DriSelection
[Index
] = 0x00;
720 // Get the EFI Loaded Image Device Path Protocol
722 LoadedImageDevicePath
= NULL
;
723 Status
= gBS
->HandleProtocol (
724 mDriverImageHandleBuffer
[Index
],
725 &gEfiLoadedImageDevicePathProtocolGuid
,
726 (VOID
**) &LoadedImageDevicePath
728 if (LoadedImageDevicePath
== NULL
) {
729 FakeNvData
->DriSelection
[Index
] = 0x00;
733 if (FakeNvData
->PciDeviceFilter
== 0x01) {
735 // only care the driver which is in a Pci device option rom,
736 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
738 if (!EFI_ERROR (Status
)) {
739 Status
= gBS
->HandleProtocol(
740 LoadedImage
->DeviceHandle
,
741 &gEfiBusSpecificDriverOverrideProtocolGuid
,
742 (VOID
**) &BusSpecificDriverOverride
744 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
745 FakeNvData
->DriSelection
[Index
] = 0x00;
749 FakeNvData
->DriSelection
[Index
] = 0x00;
755 // For driver name, try to get its component name, if fail, get its image name,
756 // if also fail, give a default name.
758 FreeDriverName
= FALSE
;
759 DriverName
= GetComponentName (DriverBindingHandle
);
760 if (DriverName
== NULL
) {
762 // get its image name
764 DriverName
= GetImageName (LoadedImage
);
766 if (DriverName
== NULL
) {
768 // give a default name
770 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME
), &DriverName
);
771 ASSERT (DriverName
!= NULL
);
772 FreeDriverName
= TRUE
; // the DriverName string need to free pool
777 // Step2 Export the driver name string and create check box item in second page
781 // First create the driver image name
783 NewString
= AllocateZeroPool (StrSize (DriverName
));
784 ASSERT (NewString
!= NULL
);
785 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol
[mSelectedCtrIndex
], LoadedImageDevicePath
, &mMappingDataBase
, NULL
, NULL
))) {
786 FakeNvData
->DriSelection
[Index
] = 0x00;
788 FakeNvData
->DriSelection
[Index
] = 0x01;
789 mLastSavedDriverImageNum
++;
791 StrCat (NewString
, DriverName
);
792 NewStringToken
= mDriverImageToken
[Index
];
793 if (NewStringToken
== 0) {
794 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
796 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
798 mDriverImageToken
[Index
] = NewStringToken
;
799 ASSERT_EFI_ERROR (Status
);
800 FreePool (NewString
);
801 if (FreeDriverName
) {
802 FreePool (DriverName
);
806 // Second create the driver image device path as item help string
808 DriverName
= DevicePathToStr (LoadedImageDevicePath
);
810 NewString
= AllocateZeroPool (StrSize (DriverName
));
811 ASSERT (NewString
!= NULL
);
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 FreePool (NewString
);
822 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 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
;
872 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
873 IFR_OPTION
*IfrOptionList
;
874 UINTN SelectedDriverImageNum
;
875 UINT32 DriverImageNO
;
881 // Following code will be run if user select 'order ... priority' item in second page
882 // Prepare third page. In third page, user will order the drivers priority which are selected in second page
884 mCurrentPage
= FORM_ID_ORDER
;
886 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
887 UpdateData
.Offset
= 0;
888 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
889 ASSERT (UpdateData
.Data
!= NULL
);
891 // Clear third page form
894 Private
->RegisteredHandle
,
895 &mPlatformOverridesManagerGuid
,
903 // Check how many drivers have been selected
905 SelectedDriverImageNum
= 0;
906 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
907 if (FakeNvData
->DriSelection
[Index
] != 0) {
908 SelectedDriverImageNum
++;
912 mSelectedDriverImageNum
= SelectedDriverImageNum
;
913 if (SelectedDriverImageNum
== 0) {
917 IfrOptionList
= AllocateZeroPool (sizeof (IFR_OPTION
) * mSelectedDriverImageNum
);
918 ASSERT (IfrOptionList
!= NULL
);
920 // Create order list for those selected drivers
922 SelectedDriverImageNum
= 0;
923 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
924 if (FakeNvData
->DriSelection
[Index
] != 0) {
925 IfrOptionList
[SelectedDriverImageNum
].StringToken
= mDriverImageToken
[Index
];
927 // Use the NO. in driver binding buffer as value, will use it later
929 IfrOptionList
[SelectedDriverImageNum
].Value
.u8
= (UINT8
) (Index
+ 1);
930 IfrOptionList
[SelectedDriverImageNum
].Flags
= 0;
933 // Get the EFI Loaded Image Device Path Protocol
935 LoadedImageDevicePath
= NULL
;
936 gBS
->HandleProtocol (
937 mDriverImageHandleBuffer
[Index
],
938 &gEfiLoadedImageDevicePathProtocolGuid
,
939 (VOID
**) &LoadedImageDevicePath
941 ASSERT (LoadedImageDevicePath
!= NULL
);
944 // Check the driver DriverImage's order number in mapping database
948 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
949 LoadedImageDevicePath
,
954 if (DriverImageNO
== 0) {
955 DriverImageNO
= (UINT32
) mLastSavedDriverImageNum
+ 1;
956 mLastSavedDriverImageNum
++;
958 TempNO
[SelectedDriverImageNum
] = DriverImageNO
;
959 SelectedDriverImageNum
++;
963 ASSERT (SelectedDriverImageNum
== mSelectedDriverImageNum
);
965 // NvRamMap Must be clear firstly
967 ZeroMem (FakeNvData
->DriOrder
, sizeof (FakeNvData
->DriOrder
));
970 // Order the selected drivers according to the info already in mapping database
971 // the less order number in mapping database the less order number in NvRamMap
973 for (Index
=0; Index
< SelectedDriverImageNum
; Index
++) {
975 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
978 for (Index1
=0; Index1
< SelectedDriverImageNum
; Index1
++) {
979 if (TempNO
[Index1
] < TempNO
[MinNO
]) {
984 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
986 FakeNvData
->DriOrder
[Index
] =IfrOptionList
[MinNO
].Value
.u8
;
987 TempNO
[MinNO
] = MAX_CHOICE_NUM
+ 1;
990 CreateOrderedListOpCode (
991 (UINT16
) DRIVER_ORDER_QUESTION_ID
,
992 VARSTORE_ID_PLAT_OVER_MNGR
,
993 (UINT16
) DRIVER_ORDER_VAR_OFFSET
,
994 mControllerToken
[mSelectedCtrIndex
],
995 mControllerToken
[mSelectedCtrIndex
],
996 EFI_IFR_FLAG_RESET_REQUIRED
,
998 EFI_IFR_NUMERIC_SIZE_1
,
999 (UINT8
) MAX_CHOICE_NUM
,
1001 SelectedDriverImageNum
,
1006 // Update third page form
1009 Private
->RegisteredHandle
,
1010 &mPlatformOverridesManagerGuid
,
1017 FreePool (IfrOptionList
);
1018 FreePool (UpdateData
.Data
);
1023 Save the save the mapping database to NV variable.
1025 @param Private Pointer to EFI_CALLBACK_INFO.
1026 @param KeyValue The callback key value of device controller item in first page.
1027 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
1029 @retval EFI_SUCCESS Always returned.
1034 IN EFI_CALLBACK_INFO
*Private
,
1036 IN PLAT_OVER_MNGR_DATA
*FakeNvData
1041 UINTN SelectedDriverImageNum
;
1042 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1044 // Following code will be run if user select 'commint changes' in third page
1045 // user enter 'Commit Changes' to save the mapping database
1047 DeleteDriverImage (mControllerDevicePathProtocol
[mSelectedCtrIndex
], NULL
, &mMappingDataBase
);
1048 for (SelectedDriverImageNum
= 0; SelectedDriverImageNum
< mSelectedDriverImageNum
; SelectedDriverImageNum
++) {
1050 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
1052 Index
= FakeNvData
->DriOrder
[SelectedDriverImageNum
] - 1;
1055 // Get the EFI Loaded Image Device Path Protocol
1057 LoadedImageDevicePath
= NULL
;
1058 Status
= gBS
->HandleProtocol (
1059 mDriverImageHandleBuffer
[Index
],
1060 &gEfiLoadedImageDevicePathProtocolGuid
,
1061 (VOID
**) &LoadedImageDevicePath
1063 ASSERT (LoadedImageDevicePath
!= NULL
);
1066 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
1067 LoadedImageDevicePath
,
1069 (UINT32
)SelectedDriverImageNum
+ 1
1072 Status
= SaveOverridesMapping (&mMappingDataBase
);
1078 This function allows a caller to extract the current configuration for one
1079 or more named elements from the target driver.
1081 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1082 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1083 @param Progress On return, points to a character in the Request string.
1084 Points to the string's null terminator if request was successful.
1085 Points to the most recent '&' before the first failing name/value
1086 pair (or the beginning of the string if the failure is in the
1087 first name/value pair) if the request was not successful.
1088 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
1089 has all values filled in for the names in the Request string.
1090 String to be allocated by the called function.
1092 @retval EFI_SUCCESS The Results is filled with the requested values.
1093 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
1094 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
1095 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1100 PlatOverMngrExtractConfig (
1101 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1102 IN CONST EFI_STRING Request
,
1103 OUT EFI_STRING
*Progress
,
1104 OUT EFI_STRING
*Results
1108 EFI_CALLBACK_INFO
*Private
;
1109 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1111 if (Request
== NULL
) {
1112 return EFI_NOT_FOUND
;
1115 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1116 HiiConfigRouting
= Private
->HiiConfigRouting
;
1119 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1121 Status
= HiiConfigRouting
->BlockToConfig (
1124 (UINT8
*) &Private
->FakeNvData
,
1125 sizeof (PLAT_OVER_MNGR_DATA
),
1133 This function processes the results of changes in configuration.
1135 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1136 @param Configuration A null-terminated Unicode string in <ConfigRequest> format.
1137 @param Progress A pointer to a string filled in with the offset of the most
1138 recent '&' before the first failing name/value pair (or the
1139 beginning of the string if the failure is in the first
1140 name/value pair) or the terminating NULL if all was successful.
1142 @retval EFI_SUCCESS The Results is processed successfully.
1143 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1144 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1149 PlatOverMngrRouteConfig (
1150 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1151 IN CONST EFI_STRING Configuration
,
1152 OUT EFI_STRING
*Progress
1155 EFI_CALLBACK_INFO
*Private
;
1159 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1161 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1163 FakeNvData
= &Private
->FakeNvData
;
1164 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1165 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1166 if (EFI_ERROR (Status
)) {
1170 if (mCurrentPage
== FORM_ID_DRIVER
) {
1171 KeyValue
= KEY_VALUE_DRIVER_GOTO_ORDER
;
1172 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1173 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1174 CommintChanges (Private
, KeyValue
, FakeNvData
);
1176 // Since UpdatePrioritySelectPage will change mCurrentPage,
1177 // should ensure the mCurrentPage still indicate the second page here
1179 mCurrentPage
= FORM_ID_DRIVER
;
1182 if (mCurrentPage
== FORM_ID_ORDER
) {
1183 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1184 CommintChanges (Private
, KeyValue
, FakeNvData
);
1190 This is the function that is called to provide results data to the driver. This data
1191 consists of a unique key which is used to identify what data is either being passed back
1194 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1195 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1196 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1197 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1198 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1199 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1200 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1201 KeyValue == 0x1800 : user select 'commint changes' in third page
1202 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1203 @param Type The type of value for the question.
1204 @param Value A pointer to the data being sent to the original exporting driver.
1205 @param ActionRequest On return, points to the action requested by the callback function.
1207 @retval EFI_SUCCESS Always returned.
1212 PlatOverMngrCallback (
1213 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1214 IN EFI_BROWSER_ACTION Action
,
1215 IN EFI_QUESTION_ID KeyValue
,
1217 IN EFI_IFR_TYPE_VALUE
*Value
,
1218 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1221 EFI_CALLBACK_INFO
*Private
;
1223 EFI_STRING_ID NewStringToken
;
1225 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1228 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1230 FakeNvData
= &Private
->FakeNvData
;
1231 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1232 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1233 if (EFI_ERROR (Status
)) {
1237 if (KeyValue
== KEY_VALUE_DEVICE_REFRESH
||
1238 KeyValue
== KEY_VALUE_DEVICE_FILTER
||
1239 KeyValue
== KEY_VALUE_DRIVER_GOTO_PREVIOUS
1241 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1243 // Update page title string
1245 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1246 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"First, Select the controller by device path");
1247 ASSERT_EFI_ERROR (Status
);
1250 if (((KeyValue
>= KEY_VALUE_DEVICE_OFFSET
) && (KeyValue
< KEY_VALUE_DEVICE_MAX
)) || (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
)) {
1251 if (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
) {
1252 KeyValue
= (EFI_QUESTION_ID
) (mSelectedCtrIndex
+ KEY_VALUE_DEVICE_OFFSET
);
1254 UpdateBindingDriverSelectPage (Private
, KeyValue
, FakeNvData
);
1256 // Update page title string
1258 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1259 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Second, Select drivers for the previous selected controller");
1260 ASSERT_EFI_ERROR (Status
);
1263 if (KeyValue
== KEY_VALUE_DRIVER_GOTO_ORDER
) {
1264 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1266 // Update page title string
1268 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1269 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Finally, Set the priority order for the drivers and save them");
1270 ASSERT_EFI_ERROR (Status
);
1273 if (KeyValue
== KEY_VALUE_ORDER_SAVE_AND_EXIT
) {
1274 Status
= CommintChanges (Private
, KeyValue
, FakeNvData
);
1275 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1276 if (EFI_ERROR (Status
)) {
1277 IfrLibCreatePopUp (1, &Key
, L
"Single Override Info too large, Saving Error!");
1278 return EFI_DEVICE_ERROR
;
1282 if (KeyValue
== KEY_VALUE_DEVICE_CLEAR
) {
1284 // Deletes all environment variable(s) that contain the override mappings info
1286 FreeMappingDatabase (&mMappingDataBase
);
1287 Status
= SaveOverridesMapping (&mMappingDataBase
);
1288 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1291 // Pass changed uncommitted data back to Form Browser
1293 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1294 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) FakeNvData
, NULL
);
1300 The driver Entry Point. The funciton will export a disk device class formset and
1301 its callback function to hii database.
1303 @param ImageHandle The firmware allocated handle for the EFI image.
1304 @param SystemTable A pointer to the EFI System Table.
1306 @retval EFI_SUCCESS The entry point is executed successfully.
1307 @retval other Some error occurs when executing this entry point.
1313 IN EFI_HANDLE ImageHandle
,
1314 IN EFI_SYSTEM_TABLE
*SystemTable
1318 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
1319 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
1320 EFI_CALLBACK_INFO
*CallbackInfo
;
1321 EFI_HANDLE DriverHandle
;
1322 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
1325 // There should only be one HII protocol
1327 Status
= gBS
->LocateProtocol (
1328 &gEfiHiiDatabaseProtocolGuid
,
1330 (VOID
**) &HiiDatabase
1332 if (EFI_ERROR (Status
)) {
1337 // There should only be one Form Configuration protocol
1339 Status
= gBS
->LocateProtocol (
1340 &gEfiFormBrowser2ProtocolGuid
,
1342 (VOID
**) &FormBrowser2
1344 if (EFI_ERROR (Status
)) {
1348 CallbackInfo
= AllocateZeroPool (sizeof (EFI_CALLBACK_INFO
));
1349 if (CallbackInfo
== NULL
) {
1350 return EFI_BAD_BUFFER_SIZE
;
1353 CallbackInfo
->Signature
= EFI_CALLBACK_INFO_SIGNATURE
;
1354 CallbackInfo
->ConfigAccess
.ExtractConfig
= PlatOverMngrExtractConfig
;
1355 CallbackInfo
->ConfigAccess
.RouteConfig
= PlatOverMngrRouteConfig
;
1356 CallbackInfo
->ConfigAccess
.Callback
= PlatOverMngrCallback
;
1359 // Create driver handle used by HII database
1361 Status
= HiiLibCreateHiiDriverHandle (&DriverHandle
);
1362 if (EFI_ERROR (Status
)) {
1365 CallbackInfo
->DriverHandle
= DriverHandle
;
1368 // Install Config Access protocol to driver handle
1370 Status
= gBS
->InstallProtocolInterface (
1372 &gEfiHiiConfigAccessProtocolGuid
,
1373 EFI_NATIVE_INTERFACE
,
1374 &CallbackInfo
->ConfigAccess
1376 if (EFI_ERROR (Status
)) {
1381 // Publish our HII data
1383 PackageList
= HiiLibPreparePackageList (
1385 &mPlatformOverridesManagerGuid
,
1389 ASSERT (PackageList
!= NULL
);
1391 Status
= HiiDatabase
->NewPackageList (
1395 &CallbackInfo
->RegisteredHandle
1397 FreePool (PackageList
);
1399 if (EFI_ERROR (Status
)) {
1404 // Locate ConfigRouting protocol
1406 Status
= gBS
->LocateProtocol (
1407 &gEfiHiiConfigRoutingProtocolGuid
,
1409 (VOID
**) &CallbackInfo
->HiiConfigRouting
1411 if (EFI_ERROR (Status
)) {
1416 // Clear all the globle variable
1418 mDriverImageHandleCount
= 0;
1420 ZeroMem (mDriverImageToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
1421 ZeroMem (mDriverImageFilePathToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
1422 ZeroMem (mControllerToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
1423 ZeroMem (mDriverImageProtocol
, MAX_CHOICE_NUM
* sizeof (EFI_LOADED_IMAGE_PROTOCOL
*));
1428 Status
= FormBrowser2
->SendForm (
1430 &CallbackInfo
->RegisteredHandle
,
1437 if (EFI_ERROR (Status
)) {
1441 Status
= HiiDatabase
->RemovePackageList (HiiDatabase
, CallbackInfo
->RegisteredHandle
);
1442 if (EFI_ERROR (Status
)) {
1449 if (CallbackInfo
->DriverHandle
!= NULL
) {
1450 HiiLibDestroyHiiDriverHandle (CallbackInfo
->DriverHandle
);
1452 if (CallbackInfo
!= NULL
) {
1453 FreePool (CallbackInfo
);
1460 Converting a given device to an unicode string.
1462 This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol
1463 does not installed, then return unknown device path L"?" directly.
1465 @param DevPath Given device path instance
1467 @return Converted string from given device path.
1468 @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting.
1472 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1476 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
1479 if (DevPath
== NULL
) {
1483 Status
= gBS
->LocateProtocol (
1484 &gEfiDevicePathToTextProtocolGuid
,
1486 (VOID
**) &DevPathToText
1488 if (!EFI_ERROR (Status
)) {
1489 ToText
= DevPathToText
->ConvertDevicePathToText (
1494 ASSERT (ToText
!= NULL
);