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
;
40 STATIC EFI_HANDLE mSelectedCtrDPHandle
;
42 STATIC CFG_PROTOCOL_INVOKER_CHOICE mChoice
[MAX_CHOICE_NUM
];
44 STATIC UINTN mSelectedCtrIndex
;
45 STATIC EFI_STRING_ID mControllerToken
[MAX_CHOICE_NUM
];
47 STATIC UINTN mDriverImageHandleCount
;
48 STATIC EFI_STRING_ID mDriverImageToken
[MAX_CHOICE_NUM
];
49 STATIC EFI_STRING_ID mDriverImageFilePathToken
[MAX_CHOICE_NUM
];
50 STATIC EFI_LOADED_IMAGE_PROTOCOL
*mDriverImageProtocol
[MAX_CHOICE_NUM
];
51 STATIC EFI_DEVICE_PATH_PROTOCOL
*mControllerDevicePathProtocol
[MAX_CHOICE_NUM
];
52 STATIC UINTN mSelectedDriverImageNum
;
53 STATIC UINTN mLastSavedDriverImageNum
;
54 STATIC CHAR8 mLanguage
[RFC_3066_ENTRY_SIZE
];
55 STATIC UINT16 mCurrentPage
;
58 The driver Entry Point. The funciton will export a disk device class formset and
59 its callback function to hii database.
61 @param ImageHandle The firmware allocated handle for the EFI image.
62 @param SystemTable A pointer to the EFI System Table.
64 @retval EFI_SUCCESS The entry point is executed successfully.
65 @retval other Some error occurs when executing this entry point.
71 IN EFI_HANDLE ImageHandle
,
72 IN EFI_SYSTEM_TABLE
*SystemTable
76 EFI_HII_DATABASE_PROTOCOL
*HiiDatabase
;
77 EFI_HII_PACKAGE_LIST_HEADER
*PackageList
;
78 EFI_CALLBACK_INFO
*CallbackInfo
;
79 EFI_HANDLE DriverHandle
;
80 EFI_FORM_BROWSER2_PROTOCOL
*FormBrowser2
;
83 // There should only be one HII protocol
85 Status
= gBS
->LocateProtocol (
86 &gEfiHiiDatabaseProtocolGuid
,
88 (VOID
**) &HiiDatabase
90 if (EFI_ERROR (Status
)) {
96 // There should only be one Form Configuration protocol
98 Status
= gBS
->LocateProtocol (
99 &gEfiFormBrowser2ProtocolGuid
,
101 (VOID
**) &FormBrowser2
103 if (EFI_ERROR (Status
)) {
108 CallbackInfo
= AllocateZeroPool (sizeof (EFI_CALLBACK_INFO
));
109 if (CallbackInfo
== NULL
) {
110 return EFI_BAD_BUFFER_SIZE
;
113 CallbackInfo
->Signature
= EFI_CALLBACK_INFO_SIGNATURE
;
114 CallbackInfo
->ConfigAccess
.ExtractConfig
= PlatOverMngrExtractConfig
;
115 CallbackInfo
->ConfigAccess
.RouteConfig
= PlatOverMngrRouteConfig
;
116 CallbackInfo
->ConfigAccess
.Callback
= PlatOverMngrCallback
;
119 // Create driver handle used by HII database
121 Status
= HiiLibCreateHiiDriverHandle (&DriverHandle
);
122 if (EFI_ERROR (Status
)) {
125 CallbackInfo
->DriverHandle
= DriverHandle
;
128 // Install Config Access protocol to driver handle
130 Status
= gBS
->InstallProtocolInterface (
132 &gEfiHiiConfigAccessProtocolGuid
,
133 EFI_NATIVE_INTERFACE
,
134 &CallbackInfo
->ConfigAccess
136 if (EFI_ERROR (Status
)) {
141 // Publish our HII data
143 PackageList
= HiiLibPreparePackageList (
145 &mPlatformOverridesManagerGuid
,
149 ASSERT (PackageList
!= NULL
);
151 Status
= HiiDatabase
->NewPackageList (
155 &CallbackInfo
->RegisteredHandle
157 gBS
->FreePool (PackageList
);
160 // Locate ConfigRouting protocol
162 Status
= gBS
->LocateProtocol (
163 &gEfiHiiConfigRoutingProtocolGuid
,
165 (VOID
**) &CallbackInfo
->HiiConfigRouting
167 if (EFI_ERROR (Status
)) {
172 // Clear all the globle variable
174 mDriverImageHandleCount
= 0;
176 ZeroMem (mDriverImageToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
177 ZeroMem (mDriverImageFilePathToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
178 ZeroMem (mControllerToken
, MAX_CHOICE_NUM
* sizeof (EFI_STRING_ID
));
179 ZeroMem (mDriverImageProtocol
, MAX_CHOICE_NUM
* sizeof (EFI_LOADED_IMAGE_PROTOCOL
*));
184 Status
= FormBrowser2
->SendForm (
186 &CallbackInfo
->RegisteredHandle
,
194 Status
= HiiDatabase
->RemovePackageList (HiiDatabase
, CallbackInfo
->RegisteredHandle
);
195 if (EFI_ERROR (Status
)) {
203 Do some convertion for the ComponentName2 supported language. It do
204 the convertion just for english language code currently.
206 @param ComponentName Pointer to the ComponentName2 protocl pointer.
207 @param Language The language string.
209 @return Return the duplication of Language if it is not english otherwise return
210 the supported english language code.
214 ConvertComponentName2SupportLanguage (
215 IN EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName
,
219 CHAR8
*SupportedLanguages
;
224 SupportedLanguages
= NULL
;
227 // treat all the english language code (en-xx or eng) equally
229 if ((AsciiStrnCmp (Language
, "en-", 3) == 0) || (AsciiStrCmp (Language
, "eng") == 0)) {
230 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "en");
231 if (SupportedLanguages
== NULL
) {
232 SupportedLanguages
= AsciiStrStr (ComponentName
->SupportedLanguages
, "eng");
237 // duplicate the Language if it is not english
239 if (SupportedLanguages
== NULL
) {
240 SupportedLanguages
= Language
;
244 // duplicate the returned language code.
246 if (AsciiStrStr (SupportedLanguages
, "-") != NULL
) {
247 LangCode
= AllocateZeroPool(32);
248 for(Index
= 0; (Index
< 31) && (SupportedLanguages
[Index
] != '\0') && (SupportedLanguages
[Index
] != ';'); Index
++) {
249 LangCode
[Index
] = SupportedLanguages
[Index
];
251 LangCode
[Index
] = '\0';
253 LangCode
= AllocateZeroPool(4);
254 for(Index
= 0; (Index
< 3) && (SupportedLanguages
[Index
] != '\0'); Index
++) {
255 LangCode
[Index
] = SupportedLanguages
[Index
];
257 LangCode
[Index
] = '\0';
263 Get the ComponentName or ComponentName2 protocol according to the driver binding handle
265 @param DriverBindingHandle The Handle of DriverBinding.
267 @retval !NULL Pointer into the image name if the image name is found,
268 @retval NULL Pointer to NULL if the image name is not found.
273 IN EFI_HANDLE DriverBindingHandle
277 EFI_COMPONENT_NAME_PROTOCOL
*ComponentName
;
278 EFI_COMPONENT_NAME2_PROTOCOL
*ComponentName2
;
279 CHAR8
*SupportedLanguage
;
282 ComponentName
= NULL
;
283 ComponentName2
= NULL
;
284 Status
= gBS
->OpenProtocol (
286 &gEfiComponentName2ProtocolGuid
,
287 (VOID
**) &ComponentName2
,
290 EFI_OPEN_PROTOCOL_GET_PROTOCOL
292 if (EFI_ERROR(Status
)) {
293 Status
= gBS
->OpenProtocol (
295 &gEfiComponentNameProtocolGuid
,
296 (VOID
**) &ComponentName
,
299 EFI_OPEN_PROTOCOL_GET_PROTOCOL
303 Status
= EFI_SUCCESS
;
305 if (ComponentName
!= NULL
) {
306 if (ComponentName
->GetDriverName
!= NULL
) {
307 Status
= ComponentName
->GetDriverName (
313 } else if (ComponentName2
!= NULL
) {
314 if (ComponentName2
->GetDriverName
!= NULL
) {
315 SupportedLanguage
= ConvertComponentName2SupportLanguage (ComponentName2
, mLanguage
);
316 Status
= ComponentName2
->GetDriverName (
321 gBS
->FreePool (SupportedLanguage
);
324 if (EFI_ERROR (Status
)) {
334 @param Image Image to search.
336 @retval !NULL Pointer into the image name if the image name is found,
337 @retval NULL Pointer to NULL if the image name is not found.
342 EFI_LOADED_IMAGE_PROTOCOL
*Image
346 EFI_DEVICE_PATH_PROTOCOL
*DevPath
;
347 EFI_DEVICE_PATH_PROTOCOL
*DevPathNode
;
348 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*FvFilePath
;
351 UINT32 AuthenticationStatus
;
353 EFI_FIRMWARE_VOLUME2_PROTOCOL
*FV2
;
359 if (Image
->FilePath
== NULL
) {
363 DevPath
= UnpackDevicePath (Image
->FilePath
);
365 if (DevPath
== NULL
) {
369 DevPathNode
= DevPath
;
371 while (!IsDevicePathEnd (DevPathNode
)) {
373 // Find the Fv File path
375 NameGuid
= EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*)DevPathNode
);
376 if (NameGuid
!= NULL
) {
377 FvFilePath
= (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH
*) DevPathNode
;
378 Status
= gBS
->HandleProtocol (
380 &gEfiFirmwareVolume2ProtocolGuid
,
383 if (!EFI_ERROR (Status
)) {
384 Status
= FV2
->ReadSection (
386 &FvFilePath
->FvFileName
,
387 EFI_SECTION_USER_INTERFACE
,
391 &AuthenticationStatus
393 if (!EFI_ERROR (Status
)) {
400 // Next device path node
402 DevPathNode
= NextDevicePathNode (DevPathNode
);
405 gBS
->FreePool (DevPath
);
410 Prepare the first page to let user select the device controller which need to
413 @param Private Pointer to EFI_CALLBACK_INFO.
414 @param KeyValue The callback key value of device controller item in first page.
415 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
417 @retval EFI_SUCCESS Always returned.
421 UpdateDeviceSelectPage (
422 IN EFI_CALLBACK_INFO
*Private
,
424 IN PLAT_OVER_MNGR_DATA
*FakeNvData
427 EFI_HII_UPDATE_DATA UpdateData
;
431 UINTN DevicePathHandleCount
;
433 EFI_STRING_ID NewStringToken
;
434 CHAR16
*ControllerName
;
435 EFI_DEVICE_PATH_PROTOCOL
*ControllerDevicePath
;
436 EFI_PCI_IO_PROTOCOL
*PciIo
;
437 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
440 mCurrentPage
= FORM_ID_DEVICE
;
442 // Following code will be run if user select 'Refresh' in first page
443 // During first page, user will see all currnet controller device path in system,
444 // select any device path will go to second page to select its overrides drivers
447 LangSize
= RFC_3066_ENTRY_SIZE
;
448 Status
= gRT
->GetVariable (
450 &gEfiGlobalVariableGuid
,
455 ASSERT_EFI_ERROR (Status
);
458 // Initial the mapping database in memory
460 FreeMappingDatabase (&mMappingDataBase
);
461 Status
= InitOverridesMapping (&mMappingDataBase
);
464 // Clear all the content in the first page
466 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
467 UpdateData
.Offset
= 0;
468 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
469 ASSERT (UpdateData
.Data
!= NULL
);
471 // Clear first page form
474 Private
->RegisteredHandle
,
475 &mPlatformOverridesManagerGuid
,
483 // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,
484 // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement
486 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH
);
487 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH
), &NewString
);
488 ASSERT (NewString
!= NULL
);
489 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
490 ASSERT_EFI_ERROR (Status
);
491 gBS
->FreePool (NewString
);
493 NewStringToken
= STRING_TOKEN (STR_FIRST_REFRESH_HELP
);
494 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_REFRESH_HELP
), &NewString
);
495 ASSERT (NewString
!= NULL
);
496 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
497 ASSERT_EFI_ERROR (Status
);
498 gBS
->FreePool (NewString
);
500 // created needed controller device item in first page
502 DevicePathHandleCount
= 0;
503 Status
= gBS
->LocateHandleBuffer (
505 &gEfiDevicePathProtocolGuid
,
507 &DevicePathHandleCount
,
508 &mDevicePathHandleBuffer
510 if (EFI_ERROR (Status
) || (DevicePathHandleCount
== 0)) {
514 for (Index
= 0; Index
< DevicePathHandleCount
; Index
++) {
515 if (FakeNvData
->PciDeviceFilter
== 0x01) {
517 // Only care PCI device which contain efi driver in its option rom.
521 // Check whether it is a pci device
523 ControllerDevicePath
= NULL
;
524 Status
= gBS
->OpenProtocol (
525 mDevicePathHandleBuffer
[Index
],
526 &gEfiPciIoProtocolGuid
,
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL
532 if (EFI_ERROR (Status
)) {
536 // Check whether it contain efi driver in its option rom
538 Status
= gBS
->HandleProtocol(
539 mDevicePathHandleBuffer
[Index
],
540 &gEfiBusSpecificDriverOverrideProtocolGuid
,
541 (VOID
**) &BusSpecificDriverOverride
543 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
548 ControllerDevicePath
= NULL
;
549 Status
= gBS
->OpenProtocol (
550 mDevicePathHandleBuffer
[Index
],
551 &gEfiDevicePathProtocolGuid
,
552 (VOID
**) &ControllerDevicePath
,
555 EFI_OPEN_PROTOCOL_GET_PROTOCOL
557 ASSERT_EFI_ERROR (Status
);
559 // Save the device path protocol interface
561 mControllerDevicePathProtocol
[Index
] = ControllerDevicePath
;
564 // Get the driver name
566 ControllerName
= DevicePathToStr (ControllerDevicePath
);
569 // Export the driver name string and create item in set options page
571 Len
= StrSize (ControllerName
);
572 NewString
= AllocateZeroPool (Len
+ StrSize (L
"--"));
573 if (EFI_ERROR (CheckMapping (ControllerDevicePath
,NULL
, &mMappingDataBase
, NULL
, NULL
))) {
574 StrCat (NewString
, L
"--");
576 StrCat (NewString
, L
"**");
578 StrCat (NewString
, ControllerName
);
580 NewStringToken
= mControllerToken
[Index
];
581 if (NewStringToken
== 0) {
582 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
584 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
586 ASSERT_EFI_ERROR (Status
);
587 gBS
->FreePool (NewString
);
589 // Save the device path string toke for next access use
591 mControllerToken
[Index
] = NewStringToken
;
596 STRING_TOKEN (STR_GOTO_HELP_DRIVER
),
597 EFI_IFR_FLAG_CALLBACK
,
598 (UINT16
) (Index
+ KEY_VALUE_DEVICE_OFFSET
),
604 // Update first page form
607 Private
->RegisteredHandle
,
608 &mPlatformOverridesManagerGuid
,
615 gBS
->FreePool (UpdateData
.Data
);
620 Prepare to let user select the drivers which need mapping with the device controller
621 selected in first page.
623 @param Private Pointer to EFI_CALLBACK_INFO.
624 @param KeyValue The callback key value of device controller item in first page.
625 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
627 @retval EFI_SUCCESS Always returned.
631 UpdateBindingDriverSelectPage (
632 IN EFI_CALLBACK_INFO
*Private
,
634 IN PLAT_OVER_MNGR_DATA
*FakeNvData
637 EFI_HII_UPDATE_DATA UpdateData
;
642 EFI_STRING_ID NewStringToken
;
643 EFI_STRING_ID NewStringHelpToken
;
644 UINTN DriverImageHandleCount
;
646 EFI_DRIVER_BINDING_PROTOCOL
*DriverBindingInterface
;
647 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
649 BOOLEAN FreeDriverName
;
651 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
652 EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL
*BusSpecificDriverOverride
;
653 EFI_HANDLE DriverBindingHandle
;
655 // If user select a controller item in the first page the following code will be run.
656 // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown
658 //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols
659 // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.
660 // 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.
663 mCurrentPage
= FORM_ID_DRIVER
;
665 // Switch the item callback key value to its NO. in mDevicePathHandleBuffer
667 mSelectedCtrIndex
= KeyValue
- 0x100;
668 ASSERT (mSelectedCtrIndex
< MAX_CHOICE_NUM
);
669 mLastSavedDriverImageNum
= 0;
671 // Clear all the content in dynamic page
673 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
674 UpdateData
.Offset
= 0;
675 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
676 ASSERT (UpdateData
.Data
!= NULL
);
678 // Clear second page form
681 Private
->RegisteredHandle
,
682 &mPlatformOverridesManagerGuid
,
690 // Show all driver which support loaded image protocol in second page
692 DriverImageHandleCount
= 0;
693 Status
= gBS
->LocateHandleBuffer (
695 &gEfiLoadedImageProtocolGuid
,
697 &DriverImageHandleCount
,
698 &mDriverImageHandleBuffer
700 if (EFI_ERROR (Status
) || (DriverImageHandleCount
== 0)) {
701 return EFI_NOT_FOUND
;
704 mDriverImageHandleCount
= DriverImageHandleCount
;
705 for (Index
= 0; Index
< DriverImageHandleCount
; Index
++) {
707 // Step1: Get the driver image total file path for help string and the driver name.
711 // Find driver's Loaded Image protocol
715 Status
= gBS
->OpenProtocol (
716 mDriverImageHandleBuffer
[Index
],
717 &gEfiLoadedImageProtocolGuid
,
718 (VOID
**) &LoadedImage
,
721 EFI_OPEN_PROTOCOL_GET_PROTOCOL
723 if (EFI_ERROR (Status
)) {
724 FakeNvData
->DriSelection
[Index
] = 0x00;
727 mDriverImageProtocol
[Index
] = LoadedImage
;
729 // Find its related driver binding protocol
731 DriverBindingInterface
= NULL
;
732 DriverBindingHandle
= NULL
;
733 DriverBindingInterface
= GetBindingProtocolFromImageHandle (
734 mDriverImageHandleBuffer
[Index
],
737 if (DriverBindingInterface
== NULL
) {
738 FakeNvData
->DriSelection
[Index
] = 0x00;
743 // Get the EFI Loaded Image Device Path Protocol
745 LoadedImageDevicePath
= NULL
;
746 Status
= gBS
->HandleProtocol (
747 mDriverImageHandleBuffer
[Index
],
748 &gEfiLoadedImageDevicePathProtocolGuid
,
749 (VOID
**) &LoadedImageDevicePath
751 if (LoadedImageDevicePath
== NULL
) {
752 FakeNvData
->DriSelection
[Index
] = 0x00;
756 if (FakeNvData
->PciDeviceFilter
== 0x01) {
758 // only care the driver which is in a Pci device option rom,
759 // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom
761 if (!EFI_ERROR (Status
)) {
762 Status
= gBS
->HandleProtocol(
763 LoadedImage
->DeviceHandle
,
764 &gEfiBusSpecificDriverOverrideProtocolGuid
,
765 (VOID
**) &BusSpecificDriverOverride
767 if (EFI_ERROR (Status
) || BusSpecificDriverOverride
== NULL
) {
768 FakeNvData
->DriSelection
[Index
] = 0x00;
772 FakeNvData
->DriSelection
[Index
] = 0x00;
778 // For driver name, try to get its component name, if fail, get its image name,
779 // if also fail, give a default name.
781 FreeDriverName
= FALSE
;
782 DriverName
= GetComponentName (DriverBindingHandle
);
783 if (DriverName
== NULL
) {
785 // get its image name
787 DriverName
= GetImageName (LoadedImage
);
789 if (DriverName
== NULL
) {
791 // give a default name
793 HiiLibGetStringFromHandle (Private
->RegisteredHandle
, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME
), &DriverName
);
794 ASSERT (DriverName
!= NULL
);
795 FreeDriverName
= TRUE
; // the DriverName string need to free pool
800 // Step2 Export the driver name string and create check box item in second page
804 // First create the driver image name
806 NewString
= AllocateZeroPool (StrSize (DriverName
));
807 if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol
[mSelectedCtrIndex
], LoadedImageDevicePath
, &mMappingDataBase
, NULL
, NULL
))) {
808 FakeNvData
->DriSelection
[Index
] = 0x00;
810 FakeNvData
->DriSelection
[Index
] = 0x01;
811 mLastSavedDriverImageNum
++;
813 StrCat (NewString
, DriverName
);
814 NewStringToken
= mDriverImageToken
[Index
];
815 if (NewStringToken
== 0) {
816 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringToken
, NewString
);
818 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, NewString
);
820 mDriverImageToken
[Index
] = NewStringToken
;
821 ASSERT_EFI_ERROR (Status
);
822 gBS
->FreePool (NewString
);
823 if (FreeDriverName
) {
824 gBS
->FreePool (DriverName
);
828 // Second create the driver image device path as item help string
830 DriverName
= DevicePathToStr (LoadedImageDevicePath
);
832 NewString
= AllocateZeroPool (StrSize (DriverName
));
833 StrCat (NewString
, DriverName
);
834 NewStringHelpToken
= mDriverImageFilePathToken
[Index
];
835 if (NewStringHelpToken
== 0) {
836 Status
= HiiLibNewString (Private
->RegisteredHandle
, &NewStringHelpToken
, NewString
);
838 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringHelpToken
, NewString
);
840 mDriverImageFilePathToken
[Index
] = NewStringHelpToken
;
841 ASSERT_EFI_ERROR (Status
);
842 gBS
->FreePool (NewString
);
843 gBS
->FreePool (DriverName
);
845 CreateCheckBoxOpCode (
846 (UINT16
) (DRIVER_SELECTION_QUESTION_ID
+ Index
),
847 VARSTORE_ID_PLAT_OVER_MNGR
,
848 (UINT16
) (DRIVER_SELECTION_VAR_OFFSET
+ Index
),
858 // Update second page form
861 Private
->RegisteredHandle
,
862 &mPlatformOverridesManagerGuid
,
869 gBS
->FreePool (UpdateData
.Data
);
874 Prepare to let user select the priority order of the drivers which are
875 selected in second page.
877 @param Private Pointer to EFI_CALLBACK_INFO.
878 @param KeyValue The callback key value of device controller item in first page.
879 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
881 @retval EFI_SUCCESS Always returned.
885 UpdatePrioritySelectPage (
886 IN EFI_CALLBACK_INFO
*Private
,
888 IN PLAT_OVER_MNGR_DATA
*FakeNvData
891 EFI_HII_UPDATE_DATA UpdateData
;
894 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
896 IFR_OPTION
*IfrOptionList
;
897 UINTN SelectedDriverImageNum
;
898 UINT32 DriverImageNO
;
904 // Following code will be run if user select 'order ... priority' item in second page
905 // Prepare third page. In third page, user will order the drivers priority which are selected in second page
907 mCurrentPage
= FORM_ID_ORDER
;
909 UpdateData
.BufferSize
= UPDATE_DATA_SIZE
;
910 UpdateData
.Offset
= 0;
911 UpdateData
.Data
= AllocateZeroPool (UPDATE_DATA_SIZE
);
912 ASSERT (UpdateData
.Data
!= NULL
);
914 // Clear third page form
917 Private
->RegisteredHandle
,
918 &mPlatformOverridesManagerGuid
,
926 // Check how many drivers have been selected
928 SelectedDriverImageNum
= 0;
929 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
930 if (FakeNvData
->DriSelection
[Index
] != 0) {
931 SelectedDriverImageNum
++;
935 mSelectedDriverImageNum
= SelectedDriverImageNum
;
936 if (SelectedDriverImageNum
== 0) {
940 IfrOptionList
= AllocateZeroPool (0x200);
941 ASSERT_EFI_ERROR (IfrOptionList
!= NULL
);
943 // Create order list for those selected drivers
945 SelectedDriverImageNum
= 0;
946 for (Index
= 0; Index
< mDriverImageHandleCount
; Index
++) {
947 if (FakeNvData
->DriSelection
[Index
] != 0) {
948 IfrOptionList
[SelectedDriverImageNum
].StringToken
= mDriverImageToken
[Index
];
950 // Use the NO. in driver binding buffer as value, will use it later
952 IfrOptionList
[SelectedDriverImageNum
].Value
.u8
= (UINT8
) (Index
+ 1);
953 IfrOptionList
[SelectedDriverImageNum
].Flags
= 0;
956 // Get the EFI Loaded Image Device Path Protocol
958 LoadedImageDevicePath
= NULL
;
959 gBS
->HandleProtocol (
960 mDriverImageHandleBuffer
[Index
],
961 &gEfiLoadedImageDevicePathProtocolGuid
,
962 (VOID
**) &LoadedImageDevicePath
964 ASSERT (LoadedImageDevicePath
!= NULL
);
967 // Check the driver DriverImage's order number in mapping database
971 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
972 LoadedImageDevicePath
,
977 if (DriverImageNO
== 0) {
978 DriverImageNO
= (UINT32
) mLastSavedDriverImageNum
+ 1;
979 mLastSavedDriverImageNum
++;
981 TempNO
[SelectedDriverImageNum
] = DriverImageNO
;
982 SelectedDriverImageNum
++;
986 ASSERT (SelectedDriverImageNum
== mSelectedDriverImageNum
);
988 // NvRamMap Must be clear firstly
990 ZeroMem (FakeNvData
->DriOrder
, 100);
993 // Order the selected drivers according to the info already in mapping database
994 // the less order number in mapping database the less order number in NvRamMap
996 for (Index
=0; Index
< SelectedDriverImageNum
; Index
++) {
998 // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array
1001 for (Index1
=0; Index1
< SelectedDriverImageNum
; Index1
++) {
1002 if (TempNO
[Index1
] < TempNO
[MinNO
]) {
1007 // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer
1009 FakeNvData
->DriOrder
[Index
] =IfrOptionList
[MinNO
].Value
.u8
;
1010 TempNO
[MinNO
] = 101;
1013 CreateOrderedListOpCode (
1014 (UINT16
) DRIVER_ORDER_QUESTION_ID
,
1015 VARSTORE_ID_PLAT_OVER_MNGR
,
1016 (UINT16
) DRIVER_ORDER_VAR_OFFSET
,
1017 mControllerToken
[mSelectedCtrIndex
],
1018 mControllerToken
[mSelectedCtrIndex
],
1019 EFI_IFR_FLAG_RESET_REQUIRED
,
1021 EFI_IFR_NUMERIC_SIZE_1
,
1024 SelectedDriverImageNum
,
1029 // Update third page form
1032 Private
->RegisteredHandle
,
1033 &mPlatformOverridesManagerGuid
,
1040 gBS
->FreePool (IfrOptionList
);
1041 gBS
->FreePool (UpdateData
.Data
);
1046 Save the save the mapping database to NV variable.
1048 @param Private Pointer to EFI_CALLBACK_INFO.
1049 @param KeyValue The callback key value of device controller item in first page.
1050 @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.
1052 @retval EFI_SUCCESS Always returned.
1057 IN EFI_CALLBACK_INFO
*Private
,
1059 IN PLAT_OVER_MNGR_DATA
*FakeNvData
1064 UINTN SelectedDriverImageNum
;
1065 EFI_DEVICE_PATH_PROTOCOL
*LoadedImageDevicePath
;
1067 // Following code will be run if user select 'commint changes' in third page
1068 // user enter 'Commit Changes' to save the mapping database
1070 DeleteDriverImage (mControllerDevicePathProtocol
[mSelectedCtrIndex
], NULL
, &mMappingDataBase
);
1071 for (SelectedDriverImageNum
= 0; SelectedDriverImageNum
< mSelectedDriverImageNum
; SelectedDriverImageNum
++) {
1073 // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer
1075 Index
= FakeNvData
->DriOrder
[SelectedDriverImageNum
] - 1;
1078 // Get the EFI Loaded Image Device Path Protocol
1080 LoadedImageDevicePath
= NULL
;
1081 Status
= gBS
->HandleProtocol (
1082 mDriverImageHandleBuffer
[Index
],
1083 &gEfiLoadedImageDevicePathProtocolGuid
,
1084 (VOID
**) &LoadedImageDevicePath
1086 ASSERT (LoadedImageDevicePath
!= NULL
);
1089 mControllerDevicePathProtocol
[mSelectedCtrIndex
],
1090 LoadedImageDevicePath
,
1092 (UINT32
)SelectedDriverImageNum
+ 1
1095 Status
= SaveOverridesMapping (&mMappingDataBase
);
1101 This function allows a caller to extract the current configuration for one
1102 or more named elements from the target driver.
1104 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1105 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1106 @param Progress On return, points to a character in the Request string.
1107 Points to the string's null terminator if request was successful.
1108 Points to the most recent '&' before the first failing name/value
1109 pair (or the beginning of the string if the failure is in the
1110 first name/value pair) if the request was not successful.
1111 @param Results A null-terminated Unicode string in <ConfigAltResp> format which
1112 has all values filled in for the names in the Request string.
1113 String to be allocated by the called function.
1115 @retval EFI_SUCCESS The Results is filled with the requested values.
1116 @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.
1117 @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.
1118 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1123 PlatOverMngrExtractConfig (
1124 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1125 IN CONST EFI_STRING Request
,
1126 OUT EFI_STRING
*Progress
,
1127 OUT EFI_STRING
*Results
1131 EFI_CALLBACK_INFO
*Private
;
1132 EFI_HII_CONFIG_ROUTING_PROTOCOL
*HiiConfigRouting
;
1134 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1135 HiiConfigRouting
= Private
->HiiConfigRouting
;
1138 // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
1140 Status
= HiiConfigRouting
->BlockToConfig (
1143 (UINT8
*) &Private
->FakeNvData
,
1144 sizeof (PLAT_OVER_MNGR_DATA
),
1152 This function processes the results of changes in configuration.
1154 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1155 @param Request A null-terminated Unicode string in <ConfigRequest> format.
1156 @param Progress A pointer to a string filled in with the offset of the most
1157 recent '&' before the first failing name/value pair (or the
1158 beginning of the string if the failure is in the first
1159 name/value pair) or the terminating NULL if all was successful.
1161 @retval EFI_SUCCESS The Results is processed successfully.
1162 @retval EFI_INVALID_PARAMETER Configuration is NULL.
1163 @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.
1168 PlatOverMngrRouteConfig (
1169 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1170 IN CONST EFI_STRING Configuration
,
1171 OUT EFI_STRING
*Progress
1174 EFI_CALLBACK_INFO
*Private
;
1178 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1180 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1182 FakeNvData
= &Private
->FakeNvData
;
1183 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1184 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1185 if (EFI_ERROR (Status
)) {
1189 if (mCurrentPage
== FORM_ID_DRIVER
) {
1190 KeyValue
= KEY_VALUE_DRIVER_GOTO_ORDER
;
1191 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1192 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1193 CommintChanges (Private
, KeyValue
, FakeNvData
);
1195 // Since UpdatePrioritySelectPage will change mCurrentPage,
1196 // should ensure the mCurrentPage still indicate the second page here
1198 mCurrentPage
= FORM_ID_DRIVER
;
1201 if (mCurrentPage
== FORM_ID_ORDER
) {
1202 KeyValue
= KEY_VALUE_ORDER_SAVE_AND_EXIT
;
1203 CommintChanges (Private
, KeyValue
, FakeNvData
);
1209 This is the function that is called to provide results data to the driver. This data
1210 consists of a unique key which is used to identify what data is either being passed back
1213 @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
1214 @param Action A null-terminated Unicode string in <ConfigRequest> format.
1215 @param KeyValue A unique Goto OpCode callback value which record user's selection.
1216 0x100 <= KeyValue <0x500 : user select a controller item in the first page;
1217 KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page
1218 KeyValue == 0x1235 : user select 'Pci device filter' in first page
1219 KeyValue == 0x1500 : user select 'order ... priority' item in second page
1220 KeyValue == 0x1800 : user select 'commint changes' in third page
1221 KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page
1222 @param Type The type of value for the question.
1223 @param Value A pointer to the data being sent to the original exporting driver.
1224 @param ActionRequest On return, points to the action requested by the callback function.
1226 @retval EFI_SUCCESS Always returned.
1231 PlatOverMngrCallback (
1232 IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL
*This
,
1233 IN EFI_BROWSER_ACTION Action
,
1234 IN EFI_QUESTION_ID KeyValue
,
1236 IN EFI_IFR_TYPE_VALUE
*Value
,
1237 OUT EFI_BROWSER_ACTION_REQUEST
*ActionRequest
1240 EFI_CALLBACK_INFO
*Private
;
1242 EFI_STRING_ID NewStringToken
;
1244 PLAT_OVER_MNGR_DATA
*FakeNvData
;
1247 Private
= EFI_CALLBACK_INFO_FROM_THIS (This
);
1249 FakeNvData
= &Private
->FakeNvData
;
1250 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1251 Status
= GetBrowserData (NULL
, NULL
, &BufferSize
, (UINT8
*) FakeNvData
);
1252 if (EFI_ERROR (Status
)) {
1256 if (KeyValue
== KEY_VALUE_DEVICE_REFRESH
||
1257 KeyValue
== KEY_VALUE_DEVICE_FILTER
||
1258 KeyValue
== KEY_VALUE_DRIVER_GOTO_PREVIOUS
1260 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1262 // Update page title string
1264 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1265 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"First, Select the controller by device path");
1266 ASSERT_EFI_ERROR (Status
);
1269 if (((KEY_VALUE_DEVICE_OFFSET
<= KeyValue
) && (KeyValue
< KEY_VALUE_DEVICE_MAX
)) || (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
)) {
1270 if (KeyValue
== KEY_VALUE_ORDER_GOTO_PREVIOUS
) {
1271 KeyValue
= (EFI_QUESTION_ID
) (mSelectedCtrIndex
+ 0x100);
1273 UpdateBindingDriverSelectPage (Private
, KeyValue
, FakeNvData
);
1275 // Update page title string
1277 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1278 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Second, Select drivers for the previous selected controller");
1279 ASSERT_EFI_ERROR (Status
);
1282 if (KeyValue
== KEY_VALUE_DRIVER_GOTO_ORDER
) {
1283 UpdatePrioritySelectPage (Private
, KeyValue
, FakeNvData
);
1285 // Update page title string
1287 NewStringToken
= STRING_TOKEN (STR_TITLE
);
1288 Status
= HiiLibSetString (Private
->RegisteredHandle
, NewStringToken
, L
"Finally, Set the priority order for the drivers and save them");
1289 ASSERT_EFI_ERROR (Status
);
1292 if (KeyValue
== KEY_VALUE_ORDER_SAVE_AND_EXIT
) {
1293 Status
= CommintChanges (Private
, KeyValue
, FakeNvData
);
1294 *ActionRequest
= EFI_BROWSER_ACTION_REQUEST_SUBMIT
;
1295 if (EFI_ERROR (Status
)) {
1296 IfrLibCreatePopUp (1, &Key
, L
"Single Override Info too large, Saving Error!");
1297 return EFI_DEVICE_ERROR
;
1301 if (KeyValue
== KEY_VALUE_DEVICE_CLEAR
) {
1303 // Deletes all environment variable(s) that contain the override mappings info
1305 FreeMappingDatabase (&mMappingDataBase
);
1306 Status
= SaveOverridesMapping (&mMappingDataBase
);
1307 UpdateDeviceSelectPage (Private
, KeyValue
, FakeNvData
);
1310 // Pass changed uncommitted data back to Form Browser
1312 BufferSize
= sizeof (PLAT_OVER_MNGR_DATA
);
1313 Status
= SetBrowserData (NULL
, NULL
, BufferSize
, (UINT8
*) FakeNvData
, NULL
);
1319 Function unpacks a device path data structure so that all the nodes
1320 of a device path are naturally aligned.
1322 @param DevPath A pointer to a device path data structure
1324 @return If the memory for the device path is successfully allocated, then a
1325 @return pointer to the new device path is returned. Otherwise, NULL is returned.
1328 EFI_DEVICE_PATH_PROTOCOL
*
1330 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1333 EFI_DEVICE_PATH_PROTOCOL
*Src
;
1334 EFI_DEVICE_PATH_PROTOCOL
*Dest
;
1335 EFI_DEVICE_PATH_PROTOCOL
*NewPath
;
1339 // Walk device path and round sizes to valid boundries
1344 Size
+= DevicePathNodeLength (Src
);
1345 Size
+= ALIGN_SIZE (Size
);
1347 if (IsDevicePathEnd (Src
)) {
1351 Src
= NextDevicePathNode (Src
);
1354 // Allocate space for the unpacked path
1356 NewPath
= AllocateZeroPool (Size
);
1359 ASSERT (((UINTN
) NewPath
) % MIN_ALIGNMENT_SIZE
== 0);
1367 Size
= DevicePathNodeLength (Src
);
1368 CopyMem (Dest
, Src
, Size
);
1369 Size
+= ALIGN_SIZE (Size
);
1370 SetDevicePathNodeLength (Dest
, Size
);
1371 Dest
->Type
|= EFI_DP_TYPE_UNPACKED
;
1372 Dest
= (EFI_DEVICE_PATH_PROTOCOL
*) (((UINT8
*) Dest
) + Size
);
1374 if (IsDevicePathEnd (Src
)) {
1378 Src
= NextDevicePathNode (Src
);
1387 Get the description string by device path.
1389 @param DevPath The input device path.
1391 @retval !NULL The description string retured.
1392 @retval NULL The description string cannot be found.
1397 IN EFI_DEVICE_PATH_PROTOCOL
*DevPath
1402 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*DevPathToText
;
1404 if (DevPath
== NULL
) {
1408 Status
= gBS
->LocateProtocol (
1409 &gEfiDevicePathToTextProtocolGuid
,
1411 (VOID
**) &DevPathToText
1413 if (!EFI_ERROR (Status
)) {
1414 ToText
= DevPathToText
->ConvertDevicePathToText (
1419 ASSERT (ToText
!= NULL
);