--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2007 - 2008, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ PlatOverMngr.c\r
+\r
+Abstract:\r
+\r
+ A UI driver to offer a UI interface in device manager to let user configue\r
+ platform override protocol to override the default algorithm for matching\r
+ drivers to controllers.\r
+\r
+ The main flow:\r
+ 1. The UI driver dynamicly locate all controller device path.\r
+ 2. The UI driver dynamicly locate all drivers which support binding protocol.\r
+ 3. The UI driver export and dynamicly update two menu to let user select the\r
+ mapping between drivers to controllers.\r
+ 4. The UI driver save all the mapping info in NV variables which will be consumed\r
+ by platform override protocol driver to publish the platform override protocol.\r
+\r
+**/\r
+\r
+#include "PlatOverMngr.h"\r
+\r
+STATIC EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;\r
+\r
+STATIC LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);\r
+\r
+STATIC EFI_HANDLE *mDevicePathHandleBuffer;\r
+STATIC EFI_HANDLE *mDriverImageHandleBuffer;\r
+STATIC EFI_HANDLE mSelectedCtrDPHandle;\r
+\r
+STATIC CFG_PROTOCOL_INVOKER_CHOICE mChoice[MAX_CHOICE_NUM];\r
+\r
+STATIC UINTN mSelectedCtrIndex;\r
+STATIC EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];\r
+\r
+STATIC UINTN mDriverImageHandleCount;\r
+STATIC EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM];\r
+STATIC EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM];\r
+STATIC EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM];\r
+STATIC EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM];\r
+STATIC UINTN mSelectedDriverImageNum;\r
+STATIC UINTN mLastSavedDriverImageNum;\r
+STATIC CHAR8 mLanguage[RFC_3066_ENTRY_SIZE];\r
+STATIC UINT16 mCurrentPage;\r
+\r
+/**\r
+ The driver Entry Point. The funciton will export a disk device class formset and\r
+ its callback function to hii database.\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The entry point is executed successfully.\r
+ @retval other Some error occurs when executing this entry point.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatOverMngrInit (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;\r
+ EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r
+ EFI_CALLBACK_INFO *CallbackInfo;\r
+ EFI_HANDLE DriverHandle;\r
+ EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2;\r
+\r
+ //\r
+ // There should only be one HII protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiDatabaseProtocolGuid,\r
+ NULL,\r
+ (VOID **) &HiiDatabase\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status ;\r
+ }\r
+\r
+\r
+ //\r
+ // There should only be one Form Configuration protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiFormBrowser2ProtocolGuid,\r
+ NULL,\r
+ (VOID **) &FormBrowser2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;;\r
+ }\r
+\r
+\r
+ CallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));\r
+ if (CallbackInfo == NULL) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;\r
+ CallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;\r
+ CallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig;\r
+ CallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback;\r
+\r
+ //\r
+ // Create driver handle used by HII database\r
+ //\r
+ Status = HiiLibCreateHiiDriverHandle (&DriverHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ CallbackInfo->DriverHandle = DriverHandle;\r
+\r
+ //\r
+ // Install Config Access protocol to driver handle\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &DriverHandle,\r
+ &gEfiHiiConfigAccessProtocolGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &CallbackInfo->ConfigAccess\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Publish our HII data\r
+ //\r
+ PackageList = HiiLibPreparePackageList (\r
+ 2,\r
+ &mPlatformOverridesManagerGuid,\r
+ VfrBin,\r
+ PlatOverMngrStrings\r
+ );\r
+ ASSERT (PackageList != NULL);\r
+\r
+ Status = HiiDatabase->NewPackageList (\r
+ HiiDatabase,\r
+ PackageList,\r
+ DriverHandle,\r
+ &CallbackInfo->RegisteredHandle\r
+ );\r
+ gBS->FreePool (PackageList);\r
+\r
+ //\r
+ // Locate ConfigRouting protocol\r
+ //\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiHiiConfigRoutingProtocolGuid,\r
+ NULL,\r
+ (VOID **) &CallbackInfo->HiiConfigRouting\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Clear all the globle variable\r
+ //\r
+ mDriverImageHandleCount = 0;\r
+ mCurrentPage = 0;\r
+ ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
+ ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
+ ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID));\r
+ ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));\r
+\r
+ //\r
+ // Show the page\r
+ //\r
+ Status = FormBrowser2->SendForm (\r
+ FormBrowser2,\r
+ &CallbackInfo->RegisteredHandle,\r
+ 1,\r
+ NULL,\r
+ 0,\r
+ NULL,\r
+ NULL\r
+ );\r
+\r
+ Status = HiiDatabase->RemovePackageList (HiiDatabase, CallbackInfo->RegisteredHandle);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Do some convertion for the ComponentName2 supported language. It do\r
+ the convertion just for english language code currently.\r
+\r
+ @param ComponentName Pointer to the ComponentName2 protocl pointer.\r
+ @param Language The language string.\r
+\r
+ @return Return the duplication of Language if it is not english otherwise return\r
+ the supported english language code.\r
+\r
+**/\r
+CHAR8 *\r
+ConvertComponentName2SupportLanguage (\r
+ IN EFI_COMPONENT_NAME2_PROTOCOL *ComponentName,\r
+ IN CHAR8 *Language\r
+ )\r
+{\r
+ CHAR8 *SupportedLanguages;\r
+ CHAR8 *LangCode;\r
+ UINTN Index;\r
+\r
+ LangCode = NULL;\r
+ SupportedLanguages = NULL;\r
+\r
+ //\r
+ // treat all the english language code (en-xx or eng) equally\r
+ //\r
+ if ((AsciiStrnCmp (Language, "en-", 3) == 0) || (AsciiStrCmp (Language, "eng") == 0)) {\r
+ SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "en");\r
+ if (SupportedLanguages == NULL) {\r
+ SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "eng");\r
+ }\r
+ }\r
+\r
+ //\r
+ // duplicate the Language if it is not english\r
+ //\r
+ if (SupportedLanguages == NULL) {\r
+ SupportedLanguages = Language;\r
+ }\r
+\r
+ //\r
+ // duplicate the returned language code.\r
+ //\r
+ if (AsciiStrStr (SupportedLanguages, "-") != NULL) {\r
+ LangCode = AllocateZeroPool(32);\r
+ for(Index = 0; (Index < 31) && (SupportedLanguages[Index] != '\0') && (SupportedLanguages[Index] != ';'); Index++) {\r
+ LangCode[Index] = SupportedLanguages[Index];\r
+ }\r
+ LangCode[Index] = '\0';\r
+ } else {\r
+ LangCode = AllocateZeroPool(4);\r
+ for(Index = 0; (Index < 3) && (SupportedLanguages[Index] != '\0'); Index++) {\r
+ LangCode[Index] = SupportedLanguages[Index];\r
+ }\r
+ LangCode[Index] = '\0';\r
+ }\r
+ return LangCode;\r
+}\r
+\r
+/**\r
+ Get the ComponentName or ComponentName2 protocol according to the driver binding handle\r
+\r
+ @param DriverBindingHandle The Handle of DriverBinding.\r
+\r
+ @retval !NULL Pointer into the image name if the image name is found,\r
+ @retval NULL Pointer to NULL if the image name is not found.\r
+\r
+**/\r
+CHAR16 *\r
+GetComponentName (\r
+ IN EFI_HANDLE DriverBindingHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_COMPONENT_NAME_PROTOCOL *ComponentName;\r
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;\r
+ CHAR8 *SupportedLanguage;\r
+ CHAR16 *DriverName;\r
+\r
+ ComponentName = NULL;\r
+ ComponentName2 = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ DriverBindingHandle,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ (VOID **) &ComponentName2,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ Status = gBS->OpenProtocol (\r
+ DriverBindingHandle,\r
+ &gEfiComponentNameProtocolGuid,\r
+ (VOID **) &ComponentName,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ DriverName = NULL;\r
+ if (ComponentName != NULL) {\r
+ if (ComponentName->GetDriverName != NULL) {\r
+ Status = ComponentName->GetDriverName (\r
+ ComponentName,\r
+ mLanguage,\r
+ &DriverName\r
+ );\r
+ }\r
+ } else if (ComponentName2 != NULL) {\r
+ if (ComponentName2->GetDriverName != NULL) {\r
+ SupportedLanguage = ConvertComponentName2SupportLanguage (ComponentName2, mLanguage);\r
+ Status = ComponentName2->GetDriverName (\r
+ ComponentName2,\r
+ SupportedLanguage,\r
+ &DriverName\r
+ );\r
+ gBS->FreePool (SupportedLanguage);\r
+ }\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ return DriverName;\r
+}\r
+\r
+/**\r
+ Get the image name\r
+\r
+ @param Image Image to search.\r
+\r
+ @retval !NULL Pointer into the image name if the image name is found,\r
+ @retval NULL Pointer to NULL if the image name is not found.\r
+\r
+**/\r
+CHAR16 *\r
+GetImageName (\r
+ EFI_LOADED_IMAGE_PROTOCOL *Image\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevPathNode;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath;\r
+ VOID *Buffer;\r
+ UINTN BufferSize;\r
+ UINT32 AuthenticationStatus;\r
+ EFI_GUID *NameGuid;\r
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FV2;\r
+\r
+ FV2 = NULL;\r
+ Buffer = NULL;\r
+ BufferSize = 0;\r
+\r
+ if (Image->FilePath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ DevPath = UnpackDevicePath (Image->FilePath);\r
+\r
+ if (DevPath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ DevPathNode = DevPath;\r
+\r
+ while (!IsDevicePathEnd (DevPathNode)) {\r
+ //\r
+ // Find the Fv File path\r
+ //\r
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);\r
+ if (NameGuid != NULL) {\r
+ FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevPathNode;\r
+ Status = gBS->HandleProtocol (\r
+ Image->DeviceHandle,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ (VOID **) &FV2\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = FV2->ReadSection (\r
+ FV2,\r
+ &FvFilePath->FvFileName,\r
+ EFI_SECTION_USER_INTERFACE,\r
+ 0,\r
+ &Buffer,\r
+ &BufferSize,\r
+ &AuthenticationStatus\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ break;\r
+ }\r
+ Buffer = NULL;\r
+ }\r
+ }\r
+ //\r
+ // Next device path node\r
+ //\r
+ DevPathNode = NextDevicePathNode (DevPathNode);\r
+ }\r
+\r
+ gBS->FreePool (DevPath);\r
+ return Buffer;\r
+}\r
+\r
+/**\r
+ Prepare the first page to let user select the device controller which need to\r
+ add mapping drivers.\r
+\r
+ @param Private Pointer to EFI_CALLBACK_INFO.\r
+ @param KeyValue The callback key value of device controller item in first page.\r
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
+\r
+ @retval EFI_SUCCESS Always returned.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateDeviceSelectPage (\r
+ IN EFI_CALLBACK_INFO *Private,\r
+ IN UINT16 KeyValue,\r
+ IN PLAT_OVER_MNGR_DATA *FakeNvData\r
+ )\r
+{\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ EFI_STATUS Status;\r
+ UINTN LangSize;\r
+ UINTN Index;\r
+ UINTN DevicePathHandleCount;\r
+ CHAR16 *NewString;\r
+ EFI_STRING_ID NewStringToken;\r
+ CHAR16 *ControllerName;\r
+ EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath;\r
+ EFI_PCI_IO_PROTOCOL *PciIo;\r
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
+ UINTN Len;\r
+\r
+ mCurrentPage = FORM_ID_DEVICE;\r
+ //\r
+ // Following code will be run if user select 'Refresh' in first page\r
+ // During first page, user will see all currnet controller device path in system,\r
+ // select any device path will go to second page to select its overrides drivers\r
+ //\r
+\r
+ LangSize = RFC_3066_ENTRY_SIZE;\r
+ Status = gRT->GetVariable (\r
+ L"PlatformLang",\r
+ &gEfiGlobalVariableGuid,\r
+ NULL,\r
+ &LangSize,\r
+ mLanguage\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ //\r
+ // Initial the mapping database in memory\r
+ //\r
+ FreeMappingDatabase (&mMappingDataBase);\r
+ Status = InitOverridesMapping (&mMappingDataBase);\r
+\r
+ //\r
+ // Clear all the content in the first page\r
+ //\r
+ UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+ ASSERT (UpdateData.Data != NULL);\r
+ //\r
+ // Clear first page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_DEVICE,\r
+ FORM_ID_DEVICE,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers,\r
+ // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement\r
+ //\r
+ NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH);\r
+ HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), &NewString);\r
+ ASSERT (NewString != NULL);\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (NewString);\r
+\r
+ NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);\r
+ HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), &NewString);\r
+ ASSERT (NewString != NULL);\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (NewString);\r
+ //\r
+ // created needed controller device item in first page\r
+ //\r
+ DevicePathHandleCount = 0;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ &DevicePathHandleCount,\r
+ &mDevicePathHandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ for (Index = 0; Index < DevicePathHandleCount; Index++) {\r
+ if (FakeNvData->PciDeviceFilter == 0x01) {\r
+ //\r
+ // Only care PCI device which contain efi driver in its option rom.\r
+ //\r
+\r
+ //\r
+ // Check whether it is a pci device\r
+ //\r
+ ControllerDevicePath = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ mDevicePathHandleBuffer[Index],\r
+ &gEfiPciIoProtocolGuid,\r
+ (VOID **) &PciIo,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ //\r
+ // Check whether it contain efi driver in its option rom\r
+ //\r
+ Status = gBS->HandleProtocol(\r
+ mDevicePathHandleBuffer[Index],\r
+ &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+ (VOID **) &BusSpecificDriverOverride\r
+ );\r
+ if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ ControllerDevicePath = NULL;\r
+ Status = gBS->OpenProtocol (\r
+ mDevicePathHandleBuffer[Index],\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &ControllerDevicePath,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
+ //\r
+ // Save the device path protocol interface\r
+ //\r
+ mControllerDevicePathProtocol[Index] = ControllerDevicePath;\r
+\r
+ //\r
+ // Get the driver name\r
+ //\r
+ ControllerName = DevicePathToStr (ControllerDevicePath);\r
+\r
+ //\r
+ // Export the driver name string and create item in set options page\r
+ //\r
+ Len = StrSize (ControllerName);\r
+ NewString = AllocateZeroPool (Len + StrSize (L"--"));\r
+ if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {\r
+ StrCat (NewString, L"--");\r
+ } else {\r
+ StrCat (NewString, L"**");\r
+ }\r
+ StrCat (NewString, ControllerName);\r
+\r
+ NewStringToken = mControllerToken[Index];\r
+ if (NewStringToken == 0) {\r
+ Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);\r
+ } else {\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
+ }\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (NewString);\r
+ //\r
+ // Save the device path string toke for next access use\r
+ //\r
+ mControllerToken[Index] = NewStringToken;\r
+\r
+ CreateGotoOpCode (\r
+ FORM_ID_DRIVER,\r
+ NewStringToken,\r
+ STRING_TOKEN (STR_GOTO_HELP_DRIVER),\r
+ EFI_IFR_FLAG_CALLBACK,\r
+ (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET),\r
+ &UpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Update first page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_DEVICE,\r
+ FORM_ID_DEVICE,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ gBS->FreePool (UpdateData.Data);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Prepare to let user select the drivers which need mapping with the device controller\r
+ selected in first page.\r
+\r
+ @param Private Pointer to EFI_CALLBACK_INFO.\r
+ @param KeyValue The callback key value of device controller item in first page.\r
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
+\r
+ @retval EFI_SUCCESS Always returned.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdateBindingDriverSelectPage (\r
+ IN EFI_CALLBACK_INFO *Private,\r
+ IN UINT16 KeyValue,\r
+ IN PLAT_OVER_MNGR_DATA *FakeNvData\r
+ )\r
+{\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+\r
+ CHAR16 *NewString;\r
+ EFI_STRING_ID NewStringToken;\r
+ EFI_STRING_ID NewStringHelpToken;\r
+ UINTN DriverImageHandleCount;\r
+\r
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface;\r
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
+ CHAR16 *DriverName;\r
+ BOOLEAN FreeDriverName;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
+ EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;\r
+ EFI_HANDLE DriverBindingHandle;\r
+ //\r
+ // If user select a controller item in the first page the following code will be run.\r
+ // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown\r
+ //\r
+ //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols\r
+ // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol.\r
+ // 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.\r
+ //\r
+\r
+ mCurrentPage = FORM_ID_DRIVER;\r
+ //\r
+ // Switch the item callback key value to its NO. in mDevicePathHandleBuffer\r
+ //\r
+ mSelectedCtrIndex = KeyValue - 0x100;\r
+ ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);\r
+ mLastSavedDriverImageNum = 0;\r
+ //\r
+ // Clear all the content in dynamic page\r
+ //\r
+ UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+ ASSERT (UpdateData.Data != NULL);\r
+ //\r
+ // Clear second page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_DRIVER,\r
+ FORM_ID_DRIVER,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // Show all driver which support loaded image protocol in second page\r
+ //\r
+ DriverImageHandleCount = 0;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiLoadedImageProtocolGuid,\r
+ NULL,\r
+ &DriverImageHandleCount,\r
+ &mDriverImageHandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ mDriverImageHandleCount = DriverImageHandleCount;\r
+ for (Index = 0; Index < DriverImageHandleCount; Index++) {\r
+ //\r
+ // Step1: Get the driver image total file path for help string and the driver name.\r
+ //\r
+\r
+ //\r
+ // Find driver's Loaded Image protocol\r
+ //\r
+ LoadedImage =NULL;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ mDriverImageHandleBuffer[Index],\r
+ &gEfiLoadedImageProtocolGuid,\r
+ (VOID **) &LoadedImage,\r
+ NULL,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ continue;\r
+ }\r
+ mDriverImageProtocol[Index] = LoadedImage;\r
+ //\r
+ // Find its related driver binding protocol\r
+ //\r
+ DriverBindingInterface = NULL;\r
+ DriverBindingHandle = NULL;\r
+ DriverBindingInterface = GetBindingProtocolFromImageHandle (\r
+ mDriverImageHandleBuffer[Index],\r
+ &DriverBindingHandle\r
+ );\r
+ if (DriverBindingInterface == NULL) {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ continue;\r
+ }\r
+\r
+ //\r
+ // Get the EFI Loaded Image Device Path Protocol\r
+ //\r
+ LoadedImageDevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ mDriverImageHandleBuffer[Index],\r
+ &gEfiLoadedImageDevicePathProtocolGuid,\r
+ (VOID **) &LoadedImageDevicePath\r
+ );\r
+ if (LoadedImageDevicePath == NULL) {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ continue;\r
+ }\r
+\r
+ if (FakeNvData->PciDeviceFilter == 0x01) {\r
+ //\r
+ // only care the driver which is in a Pci device option rom,\r
+ // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom\r
+ //\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = gBS->HandleProtocol(\r
+ LoadedImage->DeviceHandle,\r
+ &gEfiBusSpecificDriverOverrideProtocolGuid,\r
+ (VOID **) &BusSpecificDriverOverride\r
+ );\r
+ if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ continue;\r
+ }\r
+ } else {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // For driver name, try to get its component name, if fail, get its image name,\r
+ // if also fail, give a default name.\r
+ //\r
+ FreeDriverName = FALSE;\r
+ DriverName = GetComponentName (DriverBindingHandle);\r
+ if (DriverName == NULL) {\r
+ //\r
+ // get its image name\r
+ //\r
+ DriverName = GetImageName (LoadedImage);\r
+ }\r
+ if (DriverName == NULL) {\r
+ //\r
+ // give a default name\r
+ //\r
+ HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), &DriverName);\r
+ ASSERT (DriverName != NULL);\r
+ FreeDriverName = TRUE; // the DriverName string need to free pool\r
+ }\r
+\r
+\r
+ //\r
+ // Step2 Export the driver name string and create check box item in second page\r
+ //\r
+\r
+ //\r
+ // First create the driver image name\r
+ //\r
+ NewString = AllocateZeroPool (StrSize (DriverName));\r
+ if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {\r
+ FakeNvData->DriSelection[Index] = 0x00;\r
+ } else {\r
+ FakeNvData->DriSelection[Index] = 0x01;\r
+ mLastSavedDriverImageNum++;\r
+ }\r
+ StrCat (NewString, DriverName);\r
+ NewStringToken = mDriverImageToken[Index];\r
+ if (NewStringToken == 0) {\r
+ Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);\r
+ } else {\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);\r
+ }\r
+ mDriverImageToken[Index] = NewStringToken;\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (NewString);\r
+ if (FreeDriverName) {\r
+ gBS->FreePool (DriverName);\r
+ }\r
+\r
+ //\r
+ // Second create the driver image device path as item help string\r
+ //\r
+ DriverName = DevicePathToStr (LoadedImageDevicePath);\r
+\r
+ NewString = AllocateZeroPool (StrSize (DriverName));\r
+ StrCat (NewString, DriverName);\r
+ NewStringHelpToken = mDriverImageFilePathToken[Index];\r
+ if (NewStringHelpToken == 0) {\r
+ Status = HiiLibNewString (Private->RegisteredHandle, &NewStringHelpToken, NewString);\r
+ } else {\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringHelpToken, NewString);\r
+ }\r
+ mDriverImageFilePathToken[Index] = NewStringHelpToken;\r
+ ASSERT_EFI_ERROR (Status);\r
+ gBS->FreePool (NewString);\r
+ gBS->FreePool (DriverName);\r
+\r
+ CreateCheckBoxOpCode (\r
+ (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),\r
+ VARSTORE_ID_PLAT_OVER_MNGR,\r
+ (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),\r
+ NewStringToken,\r
+ NewStringHelpToken,\r
+ 0,\r
+ 0,\r
+ &UpdateData\r
+ );\r
+ }\r
+\r
+ //\r
+ // Update second page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_DRIVER,\r
+ FORM_ID_DRIVER,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ gBS->FreePool (UpdateData.Data);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Prepare to let user select the priority order of the drivers which are\r
+ selected in second page.\r
+\r
+ @param Private Pointer to EFI_CALLBACK_INFO.\r
+ @param KeyValue The callback key value of device controller item in first page.\r
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
+\r
+ @retval EFI_SUCCESS Always returned.\r
+\r
+**/\r
+EFI_STATUS\r
+UpdatePrioritySelectPage (\r
+ IN EFI_CALLBACK_INFO *Private,\r
+ IN UINT16 KeyValue,\r
+ IN PLAT_OVER_MNGR_DATA *FakeNvData\r
+ )\r
+{\r
+ EFI_HII_UPDATE_DATA UpdateData;\r
+ UINTN Index;\r
+\r
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
+\r
+ IFR_OPTION *IfrOptionList;\r
+ UINTN SelectedDriverImageNum;\r
+ UINT32 DriverImageNO;\r
+ UINTN MinNO;\r
+ UINTN Index1;\r
+ UINTN TempNO[100];\r
+\r
+ //\r
+ // Following code will be run if user select 'order ... priority' item in second page\r
+ // Prepare third page. In third page, user will order the drivers priority which are selected in second page\r
+ //\r
+ mCurrentPage = FORM_ID_ORDER;\r
+\r
+ UpdateData.BufferSize = UPDATE_DATA_SIZE;\r
+ UpdateData.Offset = 0;\r
+ UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);\r
+ ASSERT (UpdateData.Data != NULL);\r
+ //\r
+ // Clear third page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_ORDER,\r
+ FORM_ID_ORDER,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // Check how many drivers have been selected\r
+ //\r
+ SelectedDriverImageNum = 0;\r
+ for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
+ if (FakeNvData->DriSelection[Index] != 0) {\r
+ SelectedDriverImageNum ++;\r
+ }\r
+ }\r
+\r
+ mSelectedDriverImageNum = SelectedDriverImageNum;\r
+ if (SelectedDriverImageNum == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ IfrOptionList = AllocateZeroPool (0x200);\r
+ ASSERT_EFI_ERROR (IfrOptionList != NULL);\r
+ //\r
+ // Create order list for those selected drivers\r
+ //\r
+ SelectedDriverImageNum = 0;\r
+ for (Index = 0; Index < mDriverImageHandleCount; Index++) {\r
+ if (FakeNvData->DriSelection[Index] != 0) {\r
+ IfrOptionList[SelectedDriverImageNum].StringToken = mDriverImageToken[Index];\r
+ //\r
+ // Use the NO. in driver binding buffer as value, will use it later\r
+ //\r
+ IfrOptionList[SelectedDriverImageNum].Value.u8 = (UINT8) (Index + 1);\r
+ IfrOptionList[SelectedDriverImageNum].Flags = 0;\r
+\r
+ //\r
+ // Get the EFI Loaded Image Device Path Protocol\r
+ //\r
+ LoadedImageDevicePath = NULL;\r
+ gBS->HandleProtocol (\r
+ mDriverImageHandleBuffer[Index],\r
+ &gEfiLoadedImageDevicePathProtocolGuid,\r
+ (VOID **) &LoadedImageDevicePath\r
+ );\r
+ ASSERT (LoadedImageDevicePath != NULL);\r
+\r
+ //\r
+ // Check the driver DriverImage's order number in mapping database\r
+ //\r
+ DriverImageNO = 0;\r
+ CheckMapping (\r
+ mControllerDevicePathProtocol[mSelectedCtrIndex],\r
+ LoadedImageDevicePath,\r
+ &mMappingDataBase,\r
+ NULL,\r
+ &DriverImageNO\r
+ );\r
+ if (DriverImageNO == 0) {\r
+ DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1;\r
+ mLastSavedDriverImageNum++;\r
+ }\r
+ TempNO[SelectedDriverImageNum] = DriverImageNO;\r
+ SelectedDriverImageNum ++;\r
+ }\r
+ }\r
+\r
+ ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);\r
+ //\r
+ // NvRamMap Must be clear firstly\r
+ //\r
+ ZeroMem (FakeNvData->DriOrder, 100);\r
+\r
+ //\r
+ // Order the selected drivers according to the info already in mapping database\r
+ // the less order number in mapping database the less order number in NvRamMap\r
+ //\r
+ for (Index=0; Index < SelectedDriverImageNum; Index++) {\r
+ //\r
+ // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array\r
+ //\r
+ MinNO = 0;\r
+ for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) {\r
+ if (TempNO[Index1] < TempNO[MinNO]) {\r
+ MinNO = Index1;\r
+ }\r
+ }\r
+ //\r
+ // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer\r
+ //\r
+ FakeNvData->DriOrder[Index] =IfrOptionList[MinNO].Value.u8;\r
+ TempNO[MinNO] = 101;\r
+ }\r
+\r
+ CreateOrderedListOpCode (\r
+ (UINT16) DRIVER_ORDER_QUESTION_ID,\r
+ VARSTORE_ID_PLAT_OVER_MNGR,\r
+ (UINT16) DRIVER_ORDER_VAR_OFFSET,\r
+ mControllerToken[mSelectedCtrIndex],\r
+ mControllerToken[mSelectedCtrIndex],\r
+ EFI_IFR_FLAG_RESET_REQUIRED,\r
+ 0,\r
+ EFI_IFR_NUMERIC_SIZE_1,\r
+ 100,\r
+ IfrOptionList,\r
+ SelectedDriverImageNum,\r
+ &UpdateData\r
+ );\r
+\r
+ //\r
+ // Update third page form\r
+ //\r
+ IfrLibUpdateForm (\r
+ Private->RegisteredHandle,\r
+ &mPlatformOverridesManagerGuid,\r
+ FORM_ID_ORDER,\r
+ FORM_ID_ORDER,\r
+ FALSE,\r
+ &UpdateData\r
+ );\r
+\r
+ gBS->FreePool (IfrOptionList);\r
+ gBS->FreePool (UpdateData.Data);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Save the save the mapping database to NV variable.\r
+\r
+ @param Private Pointer to EFI_CALLBACK_INFO.\r
+ @param KeyValue The callback key value of device controller item in first page.\r
+ @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA.\r
+\r
+ @retval EFI_SUCCESS Always returned.\r
+\r
+**/\r
+EFI_STATUS\r
+CommintChanges (\r
+ IN EFI_CALLBACK_INFO *Private,\r
+ IN UINT16 KeyValue,\r
+ IN PLAT_OVER_MNGR_DATA *FakeNvData\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Index;\r
+ UINTN SelectedDriverImageNum;\r
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;\r
+ //\r
+ // Following code will be run if user select 'commint changes' in third page\r
+ // user enter 'Commit Changes' to save the mapping database\r
+ //\r
+ DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase);\r
+ for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) {\r
+ //\r
+ // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer\r
+ //\r
+ Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1;\r
+\r
+ //\r
+ // Get the EFI Loaded Image Device Path Protocol\r
+ //\r
+ LoadedImageDevicePath = NULL;\r
+ Status = gBS->HandleProtocol (\r
+ mDriverImageHandleBuffer[Index],\r
+ &gEfiLoadedImageDevicePathProtocolGuid,\r
+ (VOID **) &LoadedImageDevicePath\r
+ );\r
+ ASSERT (LoadedImageDevicePath != NULL);\r
+\r
+ InsertDriverImage (\r
+ mControllerDevicePathProtocol[mSelectedCtrIndex],\r
+ LoadedImageDevicePath,\r
+ &mMappingDataBase,\r
+ (UINT32)SelectedDriverImageNum + 1\r
+ );\r
+ }\r
+ Status = SaveOverridesMapping (&mMappingDataBase);\r
+\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function allows a caller to extract the current configuration for one\r
+ or more named elements from the target driver.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param Progress On return, points to a character in the Request string.\r
+ Points to the string's null terminator if request was successful.\r
+ Points to the most recent '&' before the first failing name/value\r
+ pair (or the beginning of the string if the failure is in the\r
+ first name/value pair) if the request was not successful.\r
+ @param Results A null-terminated Unicode string in <ConfigAltResp> format which\r
+ has all values filled in for the names in the Request string.\r
+ String to be allocated by the called function.\r
+\r
+ @retval EFI_SUCCESS The Results is filled with the requested values.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results.\r
+ @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatOverMngrExtractConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Request,\r
+ OUT EFI_STRING *Progress,\r
+ OUT EFI_STRING *Results\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CALLBACK_INFO *Private;\r
+ EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting;\r
+\r
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
+ HiiConfigRouting = Private->HiiConfigRouting;\r
+\r
+ //\r
+ // Convert buffer data to <ConfigResp> by helper function BlockToConfig()\r
+ //\r
+ Status = HiiConfigRouting->BlockToConfig (\r
+ HiiConfigRouting,\r
+ Request,\r
+ (UINT8 *) &Private->FakeNvData,\r
+ sizeof (PLAT_OVER_MNGR_DATA),\r
+ Results,\r
+ Progress\r
+ );\r
+ return Status;\r
+}\r
+\r
+/**\r
+ This function processes the results of changes in configuration.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Request A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param Progress A pointer to a string filled in with the offset of the most\r
+ recent '&' before the first failing name/value pair (or the\r
+ beginning of the string if the failure is in the first\r
+ name/value pair) or the terminating NULL if all was successful.\r
+\r
+ @retval EFI_SUCCESS The Results is processed successfully.\r
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.\r
+ @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatOverMngrRouteConfig (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN CONST EFI_STRING Configuration,\r
+ OUT EFI_STRING *Progress\r
+ )\r
+{\r
+ EFI_CALLBACK_INFO *Private;\r
+ EFI_STATUS Status;\r
+ UINT16 KeyValue;\r
+ UINTN BufferSize;\r
+ PLAT_OVER_MNGR_DATA *FakeNvData;\r
+\r
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
+\r
+ FakeNvData = &Private->FakeNvData;\r
+ BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (mCurrentPage == FORM_ID_DRIVER) {\r
+ KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER;\r
+ UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
+ KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
+ CommintChanges (Private, KeyValue, FakeNvData);\r
+ //\r
+ // Since UpdatePrioritySelectPage will change mCurrentPage,\r
+ // should ensure the mCurrentPage still indicate the second page here\r
+ //\r
+ mCurrentPage = FORM_ID_DRIVER;\r
+ }\r
+\r
+ if (mCurrentPage == FORM_ID_ORDER) {\r
+ KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;\r
+ CommintChanges (Private, KeyValue, FakeNvData);\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This is the function that is called to provide results data to the driver. This data\r
+ consists of a unique key which is used to identify what data is either being passed back\r
+ or being asked for.\r
+\r
+ @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.\r
+ @param Action A null-terminated Unicode string in <ConfigRequest> format.\r
+ @param KeyValue A unique Goto OpCode callback value which record user's selection.\r
+ 0x100 <= KeyValue <0x500 : user select a controller item in the first page;\r
+ KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page\r
+ KeyValue == 0x1235 : user select 'Pci device filter' in first page\r
+ KeyValue == 0x1500 : user select 'order ... priority' item in second page\r
+ KeyValue == 0x1800 : user select 'commint changes' in third page\r
+ KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page\r
+ @param Type The type of value for the question.\r
+ @param Value A pointer to the data being sent to the original exporting driver.\r
+ @param ActionRequest On return, points to the action requested by the callback function.\r
+\r
+ @retval EFI_SUCCESS Always returned.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PlatOverMngrCallback (\r
+ IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This,\r
+ IN EFI_BROWSER_ACTION Action,\r
+ IN EFI_QUESTION_ID KeyValue,\r
+ IN UINT8 Type,\r
+ IN EFI_IFR_TYPE_VALUE *Value,\r
+ OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest\r
+ )\r
+{\r
+ EFI_CALLBACK_INFO *Private;\r
+ EFI_STATUS Status;\r
+ EFI_STRING_ID NewStringToken;\r
+ UINTN BufferSize;\r
+ PLAT_OVER_MNGR_DATA *FakeNvData;\r
+ EFI_INPUT_KEY Key;\r
+\r
+ Private = EFI_CALLBACK_INFO_FROM_THIS (This);\r
+\r
+ FakeNvData = &Private->FakeNvData;\r
+ BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
+ Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (KeyValue == KEY_VALUE_DEVICE_REFRESH ||\r
+ KeyValue == KEY_VALUE_DEVICE_FILTER ||\r
+ KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS\r
+ ) {\r
+ UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
+ //\r
+ // Update page title string\r
+ //\r
+ NewStringToken = STRING_TOKEN (STR_TITLE);\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path");\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (((KEY_VALUE_DEVICE_OFFSET <= KeyValue) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {\r
+ if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {\r
+ KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + 0x100);\r
+ }\r
+ UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);\r
+ //\r
+ // Update page title string\r
+ //\r
+ NewStringToken = STRING_TOKEN (STR_TITLE);\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller");\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {\r
+ UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);\r
+ //\r
+ // Update page title string\r
+ //\r
+ NewStringToken = STRING_TOKEN (STR_TITLE);\r
+ Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them");\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+\r
+ if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {\r
+ Status = CommintChanges (Private, KeyValue, FakeNvData);\r
+ *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;\r
+ if (EFI_ERROR (Status)) {\r
+ IfrLibCreatePopUp (1, &Key, L"Single Override Info too large, Saving Error!");\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ if (KeyValue == KEY_VALUE_DEVICE_CLEAR) {\r
+ //\r
+ // Deletes all environment variable(s) that contain the override mappings info\r
+ //\r
+ FreeMappingDatabase (&mMappingDataBase);\r
+ Status = SaveOverridesMapping (&mMappingDataBase);\r
+ UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);\r
+ }\r
+ //\r
+ // Pass changed uncommitted data back to Form Browser\r
+ //\r
+ BufferSize = sizeof (PLAT_OVER_MNGR_DATA);\r
+ Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) FakeNvData, NULL);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Function unpacks a device path data structure so that all the nodes\r
+ of a device path are naturally aligned.\r
+\r
+ @param DevPath A pointer to a device path data structure\r
+\r
+ @return If the memory for the device path is successfully allocated, then a\r
+ @return pointer to the new device path is returned. Otherwise, NULL is returned.\r
+\r
+**/\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+UnpackDevicePath (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_DEVICE_PATH_PROTOCOL *Src;\r
+ EFI_DEVICE_PATH_PROTOCOL *Dest;\r
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;\r
+ UINTN Size;\r
+\r
+ //\r
+ // Walk device path and round sizes to valid boundries\r
+ //\r
+ Src = DevPath;\r
+ Size = 0;\r
+ for (;;) {\r
+ Size += DevicePathNodeLength (Src);\r
+ Size += ALIGN_SIZE (Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ //\r
+ // Allocate space for the unpacked path\r
+ //\r
+ NewPath = AllocateZeroPool (Size);\r
+ if (NewPath) {\r
+\r
+ ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);\r
+\r
+ //\r
+ // Copy each node\r
+ //\r
+ Src = DevPath;\r
+ Dest = NewPath;\r
+ for (;;) {\r
+ Size = DevicePathNodeLength (Src);\r
+ CopyMem (Dest, Src, Size);\r
+ Size += ALIGN_SIZE (Size);\r
+ SetDevicePathNodeLength (Dest, Size);\r
+ Dest->Type |= EFI_DP_TYPE_UNPACKED;\r
+ Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);\r
+\r
+ if (IsDevicePathEnd (Src)) {\r
+ break;\r
+ }\r
+\r
+ Src = NextDevicePathNode (Src);\r
+ }\r
+ }\r
+\r
+ return NewPath;\r
+}\r
+\r
+\r
+/**\r
+ Get the description string by device path.\r
+\r
+ @param DevPath The input device path.\r
+\r
+ @retval !NULL The description string retured.\r
+ @retval NULL The description string cannot be found.\r
+\r
+**/\r
+CHAR16 *\r
+DevicePathToStr (\r
+ IN EFI_DEVICE_PATH_PROTOCOL *DevPath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *ToText;\r
+ EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;\r
+\r
+ if (DevPath == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ Status = gBS->LocateProtocol (\r
+ &gEfiDevicePathToTextProtocolGuid,\r
+ NULL,\r
+ (VOID **) &DevPathToText\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ ToText = DevPathToText->ConvertDevicePathToText (\r
+ DevPath,\r
+ FALSE,\r
+ TRUE\r
+ );\r
+ ASSERT (ToText != NULL);\r
+ return ToText;\r
+ }\r
+\r
+ return NULL;\r
+}\r