From 6d8ced29b1486afd2e96a31c96474545cba30c7f Mon Sep 17 00:00:00 2001 From: lgao4 Date: Fri, 24 Apr 2009 07:02:52 +0000 Subject: Merge application PlatOverMngr and library DxePlatDriOverLib into driver PlatDriOverrideDxe. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8169 6f19259b-4bc3-4df7-8a09-765794883524 --- .../Application/PlatOverMngr/PlatOverMngr.c | 1527 ---------------- .../Application/PlatOverMngr/PlatOverMngr.h | 73 - .../Application/PlatOverMngr/PlatOverMngr.inf | 86 - MdeModulePkg/Application/PlatOverMngr/Vfr.vfr | 109 -- .../Application/PlatOverMngr/VfrStrings.uni | Bin 10032 -> 0 bytes MdeModulePkg/Include/Guid/OverrideVariable.h | 58 - .../Include/Library/PlatformDriverOverrideLib.h | 188 -- .../DxePlatDriOverLib/DxePlatDriOverLib.inf | 67 - .../Library/DxePlatDriOverLib/PlatDriOver.h | 195 -- .../Library/DxePlatDriOverLib/PlatDriOverLib.c | 1870 ------------------- MdeModulePkg/MdeModulePkg.dec | 8 - MdeModulePkg/MdeModulePkg.dsc | 3 - .../InternalPlatDriOverrideDxe.h | 218 +++ .../PlatformDriOverrideDxe/PlatDriOverrideDxe.c | 1667 +++++++++++++++++ .../PlatformDriOverrideDxe/PlatDriOverrideLib.c | 1898 ++++++++++++++++++++ .../PlatformDriOverrideDxe/PlatOverMngr.h | 73 + .../PlatformDriOverrideDxe/PlatformDriOverride.c | 212 --- .../PlatformDriOverrideDxe.inf | 74 +- .../Universal/PlatformDriOverrideDxe/Vfr.vfr | 109 ++ .../PlatformDriOverrideDxe/VfrStrings.uni | Bin 0 -> 10032 bytes 20 files changed, 4027 insertions(+), 4408 deletions(-) delete mode 100644 MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.c delete mode 100644 MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.h delete mode 100644 MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.inf delete mode 100644 MdeModulePkg/Application/PlatOverMngr/Vfr.vfr delete mode 100644 MdeModulePkg/Application/PlatOverMngr/VfrStrings.uni delete mode 100644 MdeModulePkg/Include/Guid/OverrideVariable.h delete mode 100644 MdeModulePkg/Include/Library/PlatformDriverOverrideLib.h delete mode 100644 MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf delete mode 100644 MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h delete mode 100644 MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h delete mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr create mode 100644 MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni (limited to 'MdeModulePkg') diff --git a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.c b/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.c deleted file mode 100644 index 018917fd0a..0000000000 --- a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.c +++ /dev/null @@ -1,1527 +0,0 @@ -/** @file - - A UI application to offer a UI interface in device manager to let user configure - platform override protocol to override the default algorithm for matching - drivers to controllers. - - The main flow: - 1. The UI application dynamicly locate all controller device path. - 2. The UI application dynamicly locate all drivers which support binding protocol. - 3. The UI application export and dynamicly update two menu to let user select the - mapping between drivers to controllers. - 4. The UI application save all the mapping info in NV variables which will be consumed - by platform override protocol driver to publish the platform override protocol. - -Copyright (c) 2007 - 2008, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "PlatOverMngr.h" - -#define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k') -#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE) - -typedef struct { - UINTN Signature; - EFI_HANDLE DriverHandle; - EFI_HII_HANDLE RegisteredHandle; - PLAT_OVER_MNGR_DATA FakeNvData; - EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; -} EFI_CALLBACK_INFO; - -#pragma pack(1) - -/// -/// HII specific Vendor Device Path definition. -/// -typedef struct { - VENDOR_DEVICE_PATH VendorDevicePath; - EFI_DEVICE_PATH_PROTOCOL End; -} HII_VENDOR_DEVICE_PATH; - -#pragma pack() - -// -// uni string and Vfr Binary data. -// -extern UINT8 VfrBin[]; -extern UINT8 PlatOverMngrStrings[]; - -// -// module global data -// -EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID; -CHAR16 mVariableName[] = L"Data"; -LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase); - -EFI_HANDLE *mDevicePathHandleBuffer; -EFI_HANDLE *mDriverImageHandleBuffer; - -INTN mSelectedCtrIndex; -EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM]; -UINTN mDriverImageHandleCount; -EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM]; -EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM]; -EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM]; -EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM]; -UINTN mSelectedDriverImageNum; -UINTN mLastSavedDriverImageNum; -UINT16 mCurrentPage; -EFI_CALLBACK_INFO *mCallbackInfo; - -HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - EFI_CALLER_ID_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - -/** - Converting a given device to an unicode string. - - This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol - does not installed, then return unknown device path L"?" directly. - - @param DevPath Given device path instance - - @return Converted string from given device path. - @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting. -**/ -CHAR16 * -DevicePathToStr ( - IN EFI_DEVICE_PATH_PROTOCOL *DevPath - ); - -/** - Worker function to get the driver name by ComponentName or ComponentName2 protocol - according to the driver binding handle. - - @param DriverBindingHandle The Handle of DriverBinding. - @param ProtocolGuid The pointer to Component Name (2) protocol GUID. - @param VariableName The name of the RFC 4646 or ISO 639-2 language variable. - - @retval !NULL Pointer into the image name if the image name is found, - @retval NULL Pointer to NULL if the image name is not found. - -**/ -CHAR16 * -GetComponentNameWorker ( - IN EFI_HANDLE DriverBindingHandle, - IN EFI_GUID *ProtocolGuid, - IN CONST CHAR16 *VariableName - ) -{ - EFI_STATUS Status; - EFI_COMPONENT_NAME_PROTOCOL *ComponentName; - CHAR16 *DriverName; - CHAR8 *Language; - CHAR8 *BestLanguage; - - Status = gBS->OpenProtocol ( - DriverBindingHandle, - ProtocolGuid, - (VOID *) &ComponentName, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - return NULL; - } - - // - // Find the best matching language. - // - Language = GetEfiGlobalVariable (VariableName); - BestLanguage = GetBestLanguage ( - ComponentName->SupportedLanguages, - (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid), - Language, - NULL - ); - - DriverName = NULL; - if (BestLanguage != NULL) { - ComponentName->GetDriverName ( - ComponentName, - BestLanguage, - &DriverName - ); - FreePool (BestLanguage); - } - - if (Language != NULL) { - FreePool (Language); - } - - return DriverName; -} - - -/** - Get the driver name by ComponentName or ComponentName2 protocol - according to the driver binding handle - - @param DriverBindingHandle The Handle of DriverBinding. - - @retval !NULL Pointer into the image name if the image name is found, - @retval NULL Pointer to NULL if the image name is not found. - -**/ -CHAR16 * -GetComponentName ( - IN EFI_HANDLE DriverBindingHandle - ) -{ - CHAR16 *DriverName; - - // - // Try RFC 4646 Component Name 2 protocol first. - // - DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentName2ProtocolGuid, L"PlatformLang"); - if (DriverName == NULL) { - // - // If we can not get driver name from Component Name 2 protocol, we can try ISO 639-2 Component Name protocol. - // - DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentNameProtocolGuid, L"Lang"); - } - - return DriverName; -} - -/** - Get the image name from EFI UI section. - Get FV protocol by its loaded image protocol to abstract EFI UI section. - - @param Image Pointer to the loaded image protocol - - @retval !NULL Pointer to the image name if the image name is found, - @retval NULL NULL if the image name is not found. - -**/ -CHAR16 * -GetImageName ( - IN EFI_LOADED_IMAGE_PROTOCOL *Image - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevPathNode; - EFI_DEVICE_PATH_PROTOCOL *AlignedDevPathNode; - MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; - VOID *Buffer; - UINTN BufferSize; - UINT32 AuthenticationStatus; - EFI_GUID *NameGuid; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2; - - Fv2 = NULL; - Buffer = NULL; - BufferSize = 0; - - if (Image->FilePath == NULL) { - return NULL; - } - DevPathNode = Image->FilePath; - - while (!IsDevicePathEnd (DevPathNode)) { - // - // Make sure device path node is aligned when accessing it's FV Name Guid field. - // - AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength(DevPathNode), DevPathNode); - - // - // Find the Fv File path - // - NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)AlignedDevPathNode); - if (NameGuid != NULL) { - FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) AlignedDevPathNode; - Status = gBS->HandleProtocol ( - Image->DeviceHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &Fv2 - ); - // - // Locate Image EFI UI section to get the image name. - // - if (!EFI_ERROR (Status)) { - Status = Fv2->ReadSection ( - Fv2, - &FvFilePath->FvFileName, - EFI_SECTION_USER_INTERFACE, - 0, - &Buffer, - &BufferSize, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - FreePool (AlignedDevPathNode); - break; - } - Buffer = NULL; - } - } - - FreePool (AlignedDevPathNode); - - // - // Next device path node - // - DevPathNode = NextDevicePathNode (DevPathNode); - } - - return Buffer; -} - -/** - Prepare the first page to let user select the device controller which need to - add mapping drivers if user select 'Refresh' in first page. - During first page, user will see all currnet controller device path in system, - select any device path will go to second page to select its overrides drivers. - - @param Private Pointer to EFI_CALLBACK_INFO. - @param KeyValue The callback key value of device controller item in first page. - @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. - - @retval EFI_SUCCESS Always returned. - -**/ -EFI_STATUS -UpdateDeviceSelectPage ( - IN EFI_CALLBACK_INFO *Private, - IN UINT16 KeyValue, - IN PLAT_OVER_MNGR_DATA *FakeNvData - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN DevicePathHandleCount; - CHAR16 *NewString; - EFI_STRING_ID NewStringToken; - CHAR16 *ControllerName; - EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; - EFI_PCI_IO_PROTOCOL *PciIo; - EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; - UINTN Len; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - - // - // Set current page form ID. - // - mCurrentPage = FORM_ID_DEVICE; - - // - // Initial the mapping database in memory - // - FreeMappingDatabase (&mMappingDataBase); - InitOverridesMapping (&mMappingDataBase); - - // - // Init OpCode Handle - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = FORM_ID_DEVICE; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Clear first page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_DEVICE, - StartOpCodeHandle, // Label FORM_ID_DEVICE - EndOpCodeHandle // LABEL_END - ); - - // - // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers, - // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement - // - NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH); - NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), NULL); - ASSERT (NewString != NULL); - if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) { - ASSERT (FALSE); - } - FreePool (NewString); - - NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP); - NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), NULL); - ASSERT (NewString != NULL); - if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) { - ASSERT (FALSE); - } - FreePool (NewString); - - // - // created needed controller device item in first page - // - DevicePathHandleCount = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDevicePathProtocolGuid, - NULL, - &DevicePathHandleCount, - &mDevicePathHandleBuffer - ); - if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) { - return EFI_SUCCESS; - } - - for (Index = 0; Index < DevicePathHandleCount; Index++) { - if (FakeNvData->PciDeviceFilter == 0x01) { - // - // Only care PCI device which contain efi driver in its option rom. - // - - // - // Check whether it is a pci device - // - ControllerDevicePath = NULL; - Status = gBS->OpenProtocol ( - mDevicePathHandleBuffer[Index], - &gEfiPciIoProtocolGuid, - (VOID **) &PciIo, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - continue; - } - // - // Check whether it contain efi driver in its option rom - // - Status = gBS->HandleProtocol( - mDevicePathHandleBuffer[Index], - &gEfiBusSpecificDriverOverrideProtocolGuid, - (VOID **) &BusSpecificDriverOverride - ); - if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { - continue; - } - } - - ControllerDevicePath = NULL; - Status = gBS->OpenProtocol ( - mDevicePathHandleBuffer[Index], - &gEfiDevicePathProtocolGuid, - (VOID **) &ControllerDevicePath, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - ASSERT_EFI_ERROR (Status); - // - // Save the device path protocol interface - // - mControllerDevicePathProtocol[Index] = ControllerDevicePath; - - // - // Get the driver name - // - ControllerName = DevicePathToStr (ControllerDevicePath); - - // - // Export the driver name string and create item in set options page - // - Len = StrSize (ControllerName); - NewString = AllocateZeroPool (Len + StrSize (L"--")); - ASSERT (NewString != NULL); - if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) { - StrCat (NewString, L"--"); - } else { - StrCat (NewString, L"**"); - } - StrCat (NewString, ControllerName); - - NewStringToken = HiiSetString (Private->RegisteredHandle, mControllerToken[Index], NewString, NULL); - ASSERT (NewStringToken != 0); - FreePool (NewString); - // - // Save the device path string toke for next access use - // - mControllerToken[Index] = NewStringToken; - - HiiCreateGotoOpCode ( - StartOpCodeHandle, - FORM_ID_DRIVER, - NewStringToken, - STRING_TOKEN (STR_GOTO_HELP_DRIVER), - EFI_IFR_FLAG_CALLBACK, - (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET) - ); - } - - // - // Update first page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_DEVICE, - StartOpCodeHandle, // Label FORM_ID_DEVICE - EndOpCodeHandle // LABEL_END - ); - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - - return EFI_SUCCESS; -} - -/** - Get the first Driver Binding handle which has the specific image handle. - - @param ImageHandle The Image handle - - @return Handle to Driver binding - @retval NULL The paramter is not valid or the driver binding handle is not found. - -**/ -EFI_HANDLE -GetDriverBindingHandleFromImageHandle ( - IN EFI_HANDLE ImageHandle - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN DriverBindingHandleCount; - EFI_HANDLE *DriverBindingHandleBuffer; - EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface; - EFI_HANDLE DriverBindingHandle; - - DriverBindingHandle = NULL; - - if (ImageHandle == NULL) { - return NULL; - } - // - // Get all drivers which support driver binding protocol - // - DriverBindingHandleCount = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDriverBindingProtocolGuid, - NULL, - &DriverBindingHandleCount, - &DriverBindingHandleBuffer - ); - if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { - return NULL; - } - - // - // Get the first Driver Binding handle which has the specific image handle. - // - for (Index = 0; Index < DriverBindingHandleCount; Index++) { - DriverBindingInterface = NULL; - Status = gBS->OpenProtocol ( - DriverBindingHandleBuffer[Index], - &gEfiDriverBindingProtocolGuid, - (VOID **) &DriverBindingInterface, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - continue; - } - - if (DriverBindingInterface->ImageHandle == ImageHandle) { - DriverBindingHandle = DriverBindingHandleBuffer[Index]; - break; - } - } - - FreePool (DriverBindingHandleBuffer); - return DriverBindingHandle; -} - -/** - Prepare to let user select the drivers which need mapping with the device controller - selected in first page. - - @param Private Pointer to EFI_CALLBACK_INFO. - @param KeyValue The callback key value of device controller item in first page. - KeyValue is larger than or equal to KEY_VALUE_DEVICE_OFFSET. - @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. - - @retval EFI_SUCCESS Always returned. - -**/ -EFI_STATUS -UpdateBindingDriverSelectPage ( - IN EFI_CALLBACK_INFO *Private, - IN UINT16 KeyValue, - IN PLAT_OVER_MNGR_DATA *FakeNvData - ) -{ - EFI_STATUS Status; - UINTN Index; - CHAR16 *NewString; - EFI_STRING_ID NewStringToken; - EFI_STRING_ID NewStringHelpToken; - UINTN DriverImageHandleCount; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - CHAR16 *DriverName; - BOOLEAN FreeDriverName; - EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; - EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; - EFI_HANDLE DriverBindingHandle; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - - // - // If user select a controller item in the first page the following code will be run. - // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown - // - //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols - // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol. - // 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. - // - - mCurrentPage = FORM_ID_DRIVER; - // - // Switch the item callback key value to its NO. in mDevicePathHandleBuffer - // - mSelectedCtrIndex = KeyValue - KEY_VALUE_DEVICE_OFFSET; - ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM); - - mLastSavedDriverImageNum = 0; - - // - // Init OpCode Handle - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = FORM_ID_DRIVER; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Clear second page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_DRIVER, - StartOpCodeHandle, - EndOpCodeHandle - ); - - // - // Show all driver which support loaded image protocol in second page - // - DriverImageHandleCount = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiLoadedImageProtocolGuid, - NULL, - &DriverImageHandleCount, - &mDriverImageHandleBuffer - ); - if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) { - return EFI_NOT_FOUND; - } - - mDriverImageHandleCount = DriverImageHandleCount; - for (Index = 0; Index < DriverImageHandleCount; Index++) { - // - // Step1: Get the driver image total file path for help string and the driver name. - // - - // - // Find driver's Loaded Image protocol - // - LoadedImage =NULL; - - Status = gBS->OpenProtocol ( - mDriverImageHandleBuffer[Index], - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - FakeNvData->DriSelection[Index] = 0x00; - continue; - } - mDriverImageProtocol[Index] = LoadedImage; - // - // Find its related driver binding protocol - // - DriverBindingHandle = GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer[Index]); - if (DriverBindingHandle == NULL) { - FakeNvData->DriSelection[Index] = 0x00; - continue; - } - - // - // Get the EFI Loaded Image Device Path Protocol - // - LoadedImageDevicePath = NULL; - Status = gBS->HandleProtocol ( - mDriverImageHandleBuffer[Index], - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID **) &LoadedImageDevicePath - ); - if (LoadedImageDevicePath == NULL) { - FakeNvData->DriSelection[Index] = 0x00; - continue; - } - - if (FakeNvData->PciDeviceFilter == 0x01) { - // - // only care the driver which is in a Pci device option rom, - // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom - // - if (!EFI_ERROR (Status)) { - Status = gBS->HandleProtocol( - LoadedImage->DeviceHandle, - &gEfiBusSpecificDriverOverrideProtocolGuid, - (VOID **) &BusSpecificDriverOverride - ); - if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { - FakeNvData->DriSelection[Index] = 0x00; - continue; - } - } else { - FakeNvData->DriSelection[Index] = 0x00; - continue; - } - } - - // - // For driver name, try to get its component name, if fail, get its image name, - // if also fail, give a default name. - // - FreeDriverName = FALSE; - DriverName = GetComponentName (DriverBindingHandle); - if (DriverName == NULL) { - // - // get its image name - // - DriverName = GetImageName (LoadedImage); - } - if (DriverName == NULL) { - // - // give a default name - // - DriverName = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), NULL); - ASSERT (DriverName != NULL); - FreeDriverName = TRUE; // the DriverName string need to free pool - } - - - // - // Step2 Export the driver name string and create check box item in second page - // - - // - // First create the driver image name - // - NewString = AllocateZeroPool (StrSize (DriverName)); - ASSERT (NewString != NULL); - if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) { - FakeNvData->DriSelection[Index] = 0x00; - } else { - FakeNvData->DriSelection[Index] = 0x01; - mLastSavedDriverImageNum++; - } - StrCat (NewString, DriverName); - NewStringToken = HiiSetString (Private->RegisteredHandle, mDriverImageToken[Index], NewString, NULL); - ASSERT (NewStringToken != 0); - mDriverImageToken[Index] = NewStringToken; - FreePool (NewString); - if (FreeDriverName) { - FreePool (DriverName); - } - - // - // Second create the driver image device path as item help string - // - DriverName = DevicePathToStr (LoadedImageDevicePath); - - NewString = AllocateZeroPool (StrSize (DriverName)); - ASSERT (NewString != NULL); - StrCat (NewString, DriverName); - NewStringHelpToken = HiiSetString (Private->RegisteredHandle, mDriverImageFilePathToken[Index], NewString, NULL); - ASSERT (NewStringHelpToken != 0); - mDriverImageFilePathToken[Index] = NewStringHelpToken; - FreePool (NewString); - FreePool (DriverName); - - HiiCreateCheckBoxOpCode ( - StartOpCodeHandle, - (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index), - VARSTORE_ID_PLAT_OVER_MNGR, - (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index), - NewStringToken, - NewStringHelpToken, - 0, - 0, - NULL - ); - } - - // - // Update second page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_DRIVER, - StartOpCodeHandle, // Label FORM_ID_DRIVER - EndOpCodeHandle // LABEL_END - ); - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - return EFI_SUCCESS; -} - -/** - Prepare to let user select the priority order of the drivers which are - selected in second page. - - @param Private Pointer to EFI_CALLBACK_INFO. - @param KeyValue The callback key value of device controller item in first page. - @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. - - @retval EFI_SUCCESS Always returned. - -**/ -EFI_STATUS -UpdatePrioritySelectPage ( - IN EFI_CALLBACK_INFO *Private, - IN UINT16 KeyValue, - IN PLAT_OVER_MNGR_DATA *FakeNvData - ) -{ - UINTN Index; - EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; - UINTN SelectedDriverImageNum; - UINT32 DriverImageNO; - UINTN MinNO; - UINTN Index1; - UINTN TempNO[100]; - UINTN OrderNO[100]; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - VOID *OptionsOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - - // - // Following code will be run if user select 'order ... priority' item in second page - // Prepare third page. In third page, user will order the drivers priority which are selected in second page - // - mCurrentPage = FORM_ID_ORDER; - - // - // Init OpCode Handle - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (StartOpCodeHandle != NULL); - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (EndOpCodeHandle != NULL); - - // - // Create Hii Extend Label OpCode as the start opcode - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = FORM_ID_ORDER; - - // - // Create Hii Extend Label OpCode as the end opcode - // - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Clear third page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_ORDER, - StartOpCodeHandle, - EndOpCodeHandle - ); - - // - // Check how many drivers have been selected - // - SelectedDriverImageNum = 0; - for (Index = 0; Index < mDriverImageHandleCount; Index++) { - if (FakeNvData->DriSelection[Index] != 0) { - SelectedDriverImageNum ++; - } - } - - mSelectedDriverImageNum = SelectedDriverImageNum; - if (SelectedDriverImageNum == 0) { - return EFI_SUCCESS; - } - - OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); - ASSERT (OptionsOpCodeHandle != NULL); - - // - // Create order list for those selected drivers - // - SelectedDriverImageNum = 0; - for (Index = 0; Index < mDriverImageHandleCount; Index++) { - if (FakeNvData->DriSelection[Index] != 0) { - // - // Use the NO. in driver binding buffer as value, will use it later - // - HiiCreateOneOfOptionOpCode ( - OptionsOpCodeHandle, - mDriverImageToken[Index], - 0, - EFI_IFR_NUMERIC_SIZE_1, - Index + 1 - ); - - // - // Get the EFI Loaded Image Device Path Protocol - // - LoadedImageDevicePath = NULL; - gBS->HandleProtocol ( - mDriverImageHandleBuffer[Index], - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID **) &LoadedImageDevicePath - ); - ASSERT (LoadedImageDevicePath != NULL); - - // - // Check the driver DriverImage's order number in mapping database - // - DriverImageNO = 0; - CheckMapping ( - mControllerDevicePathProtocol[mSelectedCtrIndex], - LoadedImageDevicePath, - &mMappingDataBase, - NULL, - &DriverImageNO - ); - if (DriverImageNO == 0) { - DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1; - mLastSavedDriverImageNum++; - } - TempNO[SelectedDriverImageNum] = DriverImageNO; - OrderNO[SelectedDriverImageNum] = Index + 1; - SelectedDriverImageNum ++; - } - } - - ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum); - // - // NvRamMap Must be clear firstly - // - ZeroMem (FakeNvData->DriOrder, sizeof (FakeNvData->DriOrder)); - - // - // Order the selected drivers according to the info already in mapping database - // the less order number in mapping database the less order number in NvRamMap - // - for (Index=0; Index < SelectedDriverImageNum; Index++) { - // - // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array - // - MinNO = 0; - for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) { - if (TempNO[Index1] < TempNO[MinNO]) { - MinNO = Index1; - } - } - // - // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer - // - FakeNvData->DriOrder[Index] = (UINT8) OrderNO[MinNO]; - TempNO[MinNO] = MAX_CHOICE_NUM + 1; - } - - // - // Create Order List OpCode - // - HiiCreateOrderedListOpCode ( - StartOpCodeHandle, - (UINT16) DRIVER_ORDER_QUESTION_ID, - VARSTORE_ID_PLAT_OVER_MNGR, - (UINT16) DRIVER_ORDER_VAR_OFFSET, - mControllerToken[mSelectedCtrIndex], - mControllerToken[mSelectedCtrIndex], - EFI_IFR_FLAG_RESET_REQUIRED, - 0, - EFI_IFR_NUMERIC_SIZE_1, - (UINT8) MAX_CHOICE_NUM, - OptionsOpCodeHandle, - NULL - ); - - // - // Update third page form - // - HiiUpdateForm ( - Private->RegisteredHandle, - &mPlatformOverridesManagerGuid, - FORM_ID_ORDER, - StartOpCodeHandle, // Label FORM_ID_ORDER - EndOpCodeHandle // LABEL_END - ); - - HiiFreeOpCodeHandle (StartOpCodeHandle); - HiiFreeOpCodeHandle (EndOpCodeHandle); - HiiFreeOpCodeHandle (OptionsOpCodeHandle); - - return EFI_SUCCESS; -} - -/** - Save the save the mapping database to NV variable. - - @param Private Pointer to EFI_CALLBACK_INFO. - @param KeyValue The callback key value of device controller item in first page. - @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. - - @retval EFI_SUCCESS Always returned. - -**/ -EFI_STATUS -CommintChanges ( - IN EFI_CALLBACK_INFO *Private, - IN UINT16 KeyValue, - IN PLAT_OVER_MNGR_DATA *FakeNvData - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN SelectedDriverImageNum; - EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; - // - // Following code will be run if user select 'commint changes' in third page - // user enter 'Commit Changes' to save the mapping database - // - DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase); - for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) { - // - // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer - // - Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1; - - // - // Get the EFI Loaded Image Device Path Protocol - // - LoadedImageDevicePath = NULL; - Status = gBS->HandleProtocol ( - mDriverImageHandleBuffer[Index], - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID **) &LoadedImageDevicePath - ); - ASSERT (LoadedImageDevicePath != NULL); - - InsertDriverImage ( - mControllerDevicePathProtocol[mSelectedCtrIndex], - LoadedImageDevicePath, - &mMappingDataBase, - (UINT32)SelectedDriverImageNum + 1 - ); - } - Status = SaveOverridesMapping (&mMappingDataBase); - - return Status; -} - -/** - This function allows a caller to extract the current configuration for one - or more named elements from the target driver. - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Request A null-terminated Unicode string in format. - @param Progress On return, points to a character in the Request string. - Points to the string's null terminator if request was successful. - Points to the most recent '&' before the first failing name/value - pair (or the beginning of the string if the failure is in the - first name/value pair) if the request was not successful. - @param Results A null-terminated Unicode string in format which - has all values filled in for the names in the Request string. - String to be allocated by the called function. - - @retval EFI_SUCCESS The Results is filled with the requested values. - @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. - @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. - -**/ -EFI_STATUS -EFIAPI -PlatOverMngrExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ) -{ - EFI_STATUS Status; - EFI_CALLBACK_INFO *Private; - EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; - - if (Request == NULL) { - return EFI_NOT_FOUND; - } - - Private = EFI_CALLBACK_INFO_FROM_THIS (This); - HiiConfigRouting = Private->HiiConfigRouting; - - // - // Convert buffer data to by helper function BlockToConfig() - // - Status = HiiConfigRouting->BlockToConfig ( - HiiConfigRouting, - Request, - (UINT8 *) &Private->FakeNvData, - sizeof (PLAT_OVER_MNGR_DATA), - Results, - Progress - ); - return Status; -} - -/** - This function processes the results of changes in configuration. - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Configuration A null-terminated Unicode string in format. - @param Progress A pointer to a string filled in with the offset of the most - recent '&' before the first failing name/value pair (or the - beginning of the string if the failure is in the first - name/value pair) or the terminating NULL if all was successful. - - @retval EFI_SUCCESS The Results is processed successfully. - @retval EFI_INVALID_PARAMETER Configuration is NULL. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. - -**/ -EFI_STATUS -EFIAPI -PlatOverMngrRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - EFI_CALLBACK_INFO *Private; - UINT16 KeyValue; - PLAT_OVER_MNGR_DATA *FakeNvData; - - Private = EFI_CALLBACK_INFO_FROM_THIS (This); - FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA)); - if (FakeNvData == NULL) { - return EFI_NOT_FOUND; - } - - if (mCurrentPage == FORM_ID_DRIVER) { - KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER; - UpdatePrioritySelectPage (Private, KeyValue, FakeNvData); - KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT; - CommintChanges (Private, KeyValue, FakeNvData); - // - // Since UpdatePrioritySelectPage will change mCurrentPage, - // should ensure the mCurrentPage still indicate the second page here - // - mCurrentPage = FORM_ID_DRIVER; - } - - if (mCurrentPage == FORM_ID_ORDER) { - KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT; - CommintChanges (Private, KeyValue, FakeNvData); - } - - if (FakeNvData != NULL) { - FreePool (FakeNvData); - } - - return EFI_SUCCESS; -} - -/** - This is the function that is called to provide results data to the driver. This data - consists of a unique key which is used to identify what data is either being passed back - or being asked for. - - @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param Action A null-terminated Unicode string in format. - @param KeyValue A unique Goto OpCode callback value which record user's selection. - 0x100 <= KeyValue <0x500 : user select a controller item in the first page; - KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page - KeyValue == 0x1235 : user select 'Pci device filter' in first page - KeyValue == 0x1500 : user select 'order ... priority' item in second page - KeyValue == 0x1800 : user select 'commint changes' in third page - KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page - @param Type The type of value for the question. - @param Value A pointer to the data being sent to the original exporting driver. - @param ActionRequest On return, points to the action requested by the callback function. - - @retval EFI_SUCCESS Always returned. - -**/ -EFI_STATUS -EFIAPI -PlatOverMngrCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID KeyValue, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - EFI_CALLBACK_INFO *Private; - EFI_STATUS Status; - EFI_STRING_ID NewStringToken; - EFI_INPUT_KEY Key; - PLAT_OVER_MNGR_DATA *FakeNvData; - - Private = EFI_CALLBACK_INFO_FROM_THIS (This); - FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA)); - if (FakeNvData == NULL) { - return EFI_NOT_FOUND; - } - - if (KeyValue == KEY_VALUE_DEVICE_REFRESH || - KeyValue == KEY_VALUE_DEVICE_FILTER || - KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS - ) { - UpdateDeviceSelectPage (Private, KeyValue, FakeNvData); - // - // Update page title string - // - NewStringToken = STRING_TOKEN (STR_TITLE); - if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path", NULL) == 0) { - ASSERT (FALSE); - } - } - - if (((KeyValue >= KEY_VALUE_DEVICE_OFFSET) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) { - if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) { - KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + KEY_VALUE_DEVICE_OFFSET); - } - UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData); - // - // Update page title string - // - NewStringToken = STRING_TOKEN (STR_TITLE); - if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller", NULL) == 0) { - ASSERT (FALSE); - } - } - - if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) { - UpdatePrioritySelectPage (Private, KeyValue, FakeNvData); - // - // Update page title string - // - NewStringToken = STRING_TOKEN (STR_TITLE); - if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them", NULL) == 0) { - ASSERT (FALSE); - } - } - - if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) { - Status = CommintChanges (Private, KeyValue, FakeNvData); - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; - if (EFI_ERROR (Status)) { - CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Single Override Info too large, Saving Error!", NULL); - return EFI_DEVICE_ERROR; - } - } - - if (KeyValue == KEY_VALUE_DEVICE_CLEAR) { - // - // Deletes all environment variable(s) that contain the override mappings info - // - FreeMappingDatabase (&mMappingDataBase); - Status = SaveOverridesMapping (&mMappingDataBase); - UpdateDeviceSelectPage (Private, KeyValue, FakeNvData); - } - // - // Pass changed uncommitted data back to Form Browser - // - HiiSetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL); - - // - // Update local configuration buffer. - // - CopyMem (&Private->FakeNvData, FakeNvData, sizeof (PLAT_OVER_MNGR_DATA)); - if (FakeNvData != NULL) { - FreePool (FakeNvData); - } - - return EFI_SUCCESS; -} - -/** - The driver Entry Point. The funciton will export a disk device class formset and - its callback function to hii database. - - @param ImageHandle The firmware allocated handle for the EFI image. - @param SystemTable A pointer to the EFI System Table. - - @retval EFI_SUCCESS The entry point is executed successfully. - @retval other Some error occurs when executing this entry point. - -**/ -EFI_STATUS -EFIAPI -PlatOverMngrInit ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_STATUS Status; - EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; - - // - // There should only be one Form Configuration protocol - // - Status = gBS->LocateProtocol ( - &gEfiFormBrowser2ProtocolGuid, - NULL, - (VOID **) &FormBrowser2 - ); - if (EFI_ERROR (Status)) { - return Status; - } - - mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO)); - if (mCallbackInfo == NULL) { - return EFI_BAD_BUFFER_SIZE; - } - - mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE; - mCallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig; - mCallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig; - mCallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback; - - // - // Install Device Path Protocol and Config Access protocol to driver handle - // - Status = gBS->InstallMultipleProtocolInterfaces ( - &mCallbackInfo->DriverHandle, - &gEfiDevicePathProtocolGuid, - &mHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &mCallbackInfo->ConfigAccess, - NULL - ); - if (EFI_ERROR (Status)) { - goto Finish; - } - - // - // Publish our HII data - // - mCallbackInfo->RegisteredHandle = HiiAddPackages ( - &mPlatformOverridesManagerGuid, - mCallbackInfo->DriverHandle, - VfrBin, - PlatOverMngrStrings, - NULL - ); - if (mCallbackInfo->RegisteredHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto Finish; - } - - // - // Locate ConfigRouting protocol - // - Status = gBS->LocateProtocol ( - &gEfiHiiConfigRoutingProtocolGuid, - NULL, - (VOID **) &mCallbackInfo->HiiConfigRouting - ); - if (EFI_ERROR (Status)) { - goto Finish; - } - - // - // Clear all the globle variable - // - mDriverImageHandleCount = 0; - mCurrentPage = 0; - ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); - ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); - ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); - ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *)); - - // - // Show the page - // - Status = FormBrowser2->SendForm ( - FormBrowser2, - &mCallbackInfo->RegisteredHandle, - 1, - NULL, - 0, - NULL, - NULL - ); - - HiiRemovePackages (mCallbackInfo->RegisteredHandle); - Status = EFI_SUCCESS; - -Finish: - if (mCallbackInfo->DriverHandle != NULL) { - gBS->UninstallMultipleProtocolInterfaces ( - mCallbackInfo->DriverHandle, - &gEfiDevicePathProtocolGuid, - &mHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &mCallbackInfo->ConfigAccess, - NULL - ); - } - - if (mCallbackInfo != NULL) { - FreePool (mCallbackInfo); - } - - return Status; -} - -/** - Converting a given device to an unicode string. - - This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol - does not installed, then return unknown device path L"?" directly. - - @param DevPath Given device path instance - - @return Converted string from given device path. - @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting. -**/ -CHAR16 * -DevicePathToStr ( - IN EFI_DEVICE_PATH_PROTOCOL *DevPath - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; - CHAR16 *ToText; - - if (DevPath == NULL) { - return L""; - } - - Status = gBS->LocateProtocol ( - &gEfiDevicePathToTextProtocolGuid, - NULL, - (VOID **) &DevPathToText - ); - if (!EFI_ERROR (Status)) { - ToText = DevPathToText->ConvertDevicePathToText ( - DevPath, - FALSE, - TRUE - ); - ASSERT (ToText != NULL); - return ToText; - } - - return L"?"; -} diff --git a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.h b/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.h deleted file mode 100644 index 2d73d0ee6f..0000000000 --- a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.h +++ /dev/null @@ -1,73 +0,0 @@ -/** @file - - The defintions are required both by Source code and Vfr file. - The PLAT_OVER_MNGR_DATA structure, form guid and Ifr question ID are defined. - -Copyright (c) 2007 - 2008, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _PLAT_OVER_MNGR_H_ -#define _PLAT_OVER_MNGR_H_ - -#define PLAT_OVER_MNGR_GUID \ - { \ - 0x8614567d, 0x35be, 0x4415, {0x8d, 0x88, 0xbd, 0x7d, 0xc, 0x9c, 0x70, 0xc0} \ - } - -// -// The max number of the supported driver list. -// -#define MAX_CHOICE_NUM 0x00ff -#define UPDATE_DATA_SIZE 0x1000 - -#define FORM_ID_DEVICE 0x1100 -#define FORM_ID_DRIVER 0x1200 -#define FORM_ID_ORDER 0x1500 - -#define KEY_VALUE_DEVICE_OFFSET 0x0100 -#define KEY_VALUE_DEVICE_MAX (KEY_VALUE_DEVICE_OFFSET + MAX_CHOICE_NUM) - -#define KEY_VALUE_DEVICE_REFRESH 0x1234 -#define KEY_VALUE_DEVICE_FILTER 0x1235 -#define KEY_VALUE_DEVICE_CLEAR 0x1236 - -#define KEY_VALUE_DRIVER_GOTO_PREVIOUS 0x1300 -#define KEY_VALUE_DRIVER_GOTO_ORDER 0x1301 - -#define KEY_VALUE_ORDER_GOTO_PREVIOUS 0x2000 -#define KEY_VALUE_ORDER_SAVE_AND_EXIT 0x1800 - -#define VARSTORE_ID_PLAT_OVER_MNGR 0x1000 - -#define LABEL_END 0xffff - -typedef struct { - UINT8 DriSelection[MAX_CHOICE_NUM]; - UINT8 DriOrder[MAX_CHOICE_NUM]; - UINT8 PciDeviceFilter; -} PLAT_OVER_MNGR_DATA; - -// -// Field offset of structure PLAT_OVER_MNGR_DATA -// -#define VAR_OFFSET(Field) ((UINTN) &(((PLAT_OVER_MNGR_DATA *) 0)->Field)) -#define DRIVER_SELECTION_VAR_OFFSET (VAR_OFFSET (DriSelection)) -#define DRIVER_ORDER_VAR_OFFSET (VAR_OFFSET (DriOrder)) - -// -// Tool automatic generated Question Id start from 1 -// In order to avoid to conflict them, the Driver Selection and Order QuestionID offset is defined from 0x0500. -// -#define QUESTION_ID_OFFSET 0x0500 -#define DRIVER_SELECTION_QUESTION_ID (VAR_OFFSET (DriSelection) + QUESTION_ID_OFFSET) -#define DRIVER_ORDER_QUESTION_ID (VAR_OFFSET (DriOrder) + QUESTION_ID_OFFSET) - -#endif diff --git a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.inf b/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.inf deleted file mode 100644 index 0d5ea888bb..0000000000 --- a/MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.inf +++ /dev/null @@ -1,86 +0,0 @@ -#/** @file -# -# A UI application to offer an UI interface in device manager to let user configure -# platform override protocol to override the default algorithm for matching -# drivers to controllers. -# -# The main flow: -# 1. The UI application dynamicly locate all controller device path. -# 2. The UI application dynamicly locate all drivers which support binding protocol. -# 3. The UI application export and dynamicly update two menu to let user select the -# mapping between drivers to controllers. -# 4. The UI application save all the mapping info in NV variables for the following boot, -# which will be consumed by platform override protocol driver to publish the platform override protocol. -# -# Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved. -# -# All rights reserved. This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -#**/ - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = PlatOverMngr - FILE_GUID = 56D95BFE-F991-4898-B3BE-B8F37C927F48 - MODULE_TYPE = UEFI_APPLICATION - VERSION_STRING = 1.0 - ENTRY_POINT = PlatOverMngrInit - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources.common] - VfrStrings.uni - Vfr.vfr - PlatOverMngr.c - PlatOverMngr.h - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - BaseLib - DebugLib - UefiLib - UefiApplicationEntryPoint - UefiBootServicesTableLib - PlatformDriverOverrideLib - HiiLib - BaseMemoryLib - MemoryAllocationLib - DevicePathLib - -[Guids] -## This GUID C Name is not required for build since it is from UefiLib and not directly used by this module source. -## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"PlatformLang" this variable specifies the platform supported language string (RFC 4646 format) -## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"Lang" this variable specifies the platform supported language string (ISO 639-2 format) - gEfiIfrTianoGuid ## CONSUMES ## Guid - -[Protocols] - gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentName2Protocol exists) - gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentNameProtocol exists and ComponentName2Protocol doesn't exist) - gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name from EFI UI section if ComponentName2Protocol and ComponentNameProtocol don't exist) - gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMED (Find the PCI device if PciIo protocol is installed) - gEfiBusSpecificDriverOverrideProtocolGuid ## SOMETIMES_CONSUMED (Check whether the PCI device contains one or more efi drivers in its option rom by this protocol) - - gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMED - gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMED - gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the drivers in the second page that support DriverBindingProtocol, LoadedImageProtocol and LoadedImageDevicePathProtocol) - gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the controller device in the first page that support DevicePathProtocol) - - gEfiHiiDatabaseProtocolGuid ## CONSUMED - gEfiFormBrowser2ProtocolGuid ## CONSUMED - gEfiHiiConfigRoutingProtocolGuid ## CONSUMED - gEfiHiiConfigAccessProtocolGuid ## PRODUCED - gEfiDevicePathToTextProtocolGuid ## CONSUMED diff --git a/MdeModulePkg/Application/PlatOverMngr/Vfr.vfr b/MdeModulePkg/Application/PlatOverMngr/Vfr.vfr deleted file mode 100644 index a68073fa05..0000000000 --- a/MdeModulePkg/Application/PlatOverMngr/Vfr.vfr +++ /dev/null @@ -1,109 +0,0 @@ -// *++ -// -// Copyright (c) 2007 - 2008, Intel Corporation -// All rights reserved. This program and the accompanying materials -// are licensed and made available under the terms and conditions of the BSD License -// which accompanies this distribution. The full text of the license may be found at -// http://opensource.org/licenses/bsd-license.php -// -// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -// -// Module Name: -// -// Vfr.vfr -// -// Abstract: -// -// Platform driver Override manager formset -// -// -// --*/ - -#include "PlatOverMngr.h" - -#define EFI_DISK_DEVICE_CLASS 0x01 - -formset - guid = PLAT_OVER_MNGR_GUID, - title = STRING_TOKEN(STR_ENTRY_TITLE), - help = STRING_TOKEN(STR_TITLE_HELP), - class = EFI_DISK_DEVICE_CLASS, - subclass = 0xff, - - varstore PLAT_OVER_MNGR_DATA, - varid = VARSTORE_ID_PLAT_OVER_MNGR, - name = Data, - guid = PLAT_OVER_MNGR_GUID; - - form formid = FORM_ID_DEVICE, - title = STRING_TOKEN(STR_TITLE); - - text - help = STRING_TOKEN(STR_FIRST_REFRESH_HELP), - text = STRING_TOKEN(STR_FIRST_REFRESH), - text = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - key = KEY_VALUE_DEVICE_REFRESH; - - checkbox varid = Data.PciDeviceFilter, - prompt = STRING_TOKEN(STR_PCI_DEVICE_FILTER_PROMPT), - help = STRING_TOKEN(STR_PCI_DEVICE_FILTER_HELP), - flags = INTERACTIVE, - key = KEY_VALUE_DEVICE_FILTER, - endcheckbox; - - label FORM_ID_DEVICE; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - goto FORM_ID_DEVICE, - prompt = STRING_TOKEN(STR_CLEAR_ALL), - help = STRING_TOKEN(STR_CLEAR_ALL_HELP), - flags = INTERACTIVE | RESET_REQUIRED, - key = KEY_VALUE_DEVICE_CLEAR; - endform; - - form formid = FORM_ID_DRIVER, - title = STRING_TOKEN(STR_TITLE); - - goto FORM_ID_DEVICE, - prompt = STRING_TOKEN(STR_GOTO_PREVIOUS), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - key = KEY_VALUE_DRIVER_GOTO_PREVIOUS; - - goto FORM_ID_ORDER, - prompt = STRING_TOKEN(STR_TITLE_ORDER), - help = STRING_TOKEN(STR_TITLE_ORDER_HELP), - flags = INTERACTIVE, - key = KEY_VALUE_DRIVER_GOTO_ORDER; - - label FORM_ID_DRIVER; - label LABEL_END; - - endform; - - form formid = FORM_ID_ORDER, - title = STRING_TOKEN(STR_TITLE); - - goto FORM_ID_DRIVER, - prompt = STRING_TOKEN(STR_GOTO_PREVIOUS), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE, - key = KEY_VALUE_ORDER_GOTO_PREVIOUS; - - label FORM_ID_ORDER; - label LABEL_END; - - subtitle text = STRING_TOKEN(STR_NULL_STRING); - - goto FORM_ID_ORDER, - prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), - help = STRING_TOKEN(STR_NULL_STRING), - flags = INTERACTIVE | RESET_REQUIRED, - key = KEY_VALUE_ORDER_SAVE_AND_EXIT; - endform; - -endformset; diff --git a/MdeModulePkg/Application/PlatOverMngr/VfrStrings.uni b/MdeModulePkg/Application/PlatOverMngr/VfrStrings.uni deleted file mode 100644 index fe14d30f1f..0000000000 Binary files a/MdeModulePkg/Application/PlatOverMngr/VfrStrings.uni and /dev/null differ diff --git a/MdeModulePkg/Include/Guid/OverrideVariable.h b/MdeModulePkg/Include/Guid/OverrideVariable.h deleted file mode 100644 index 2e6601d5a5..0000000000 --- a/MdeModulePkg/Include/Guid/OverrideVariable.h +++ /dev/null @@ -1,58 +0,0 @@ -/** @file - This file defines the platform driver override variable name and variable guid. - The variable(s) contain the override mappings from Controller Device Path to a set of Driver Device Paths. - - VariableLayout { - // - // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load. - // Each variable has MaximumVariableSize limitation, so multiple variables are required to store - // large mapping infos. - // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, .... - // - UINT32 NotEnd; //Zero is the last one. - // - // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths - // There are often multi mapping entries in a variable. - // - UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i') - UINT32 DriverNum; - EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - ...... - UINT32 NotEnd; //Zero is the last one. - UINT32 SIGNATURE; - UINT32 DriverNum; - EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - ...... - } - -Copyright (c) 2008 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef __EFI_OVERRIDE_VARIABLE_GUID_H__ -#define __EFI_OVERRIDE_VARIABLE_GUID_H__ - -/// -/// This guid is used for a platform driver override variable -/// -#define EFI_OVERRIDE_VARIABLE_GUID \ - { 0x8e3d4ad5, 0xf762, 0x438a, { 0xa1, 0xc1, 0x5b, 0x9f, 0xe6, 0x8c, 0x6b, 0x15 }} - -#define EFI_PLATFORM_OVERRIDE_VARIABLE_NAME L"PlatDriOver" - -extern EFI_GUID gEfiOverrideVariableGuid; - -#endif // #ifndef __EFI_OVERRIDE_VARIABLE_GUID_H__ diff --git a/MdeModulePkg/Include/Library/PlatformDriverOverrideLib.h b/MdeModulePkg/Include/Library/PlatformDriverOverrideLib.h deleted file mode 100644 index 2af25d53d5..0000000000 --- a/MdeModulePkg/Include/Library/PlatformDriverOverrideLib.h +++ /dev/null @@ -1,188 +0,0 @@ -/** @file - Ihis library is only intended to be used by Platform Driver Override Dxe Driver and Application. - It provides basic platform driver override functions. - -Copyright (c) 2007 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _PLATFORM_DRIVER_OVERRIDE_LIB_H_ -#define _PLATFORM_DRIVER_OVERRIDE_LIB_H_ - -#include - -/** - Free all the mapping database memory resource and initialize the mapping list entry. - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_INVALID_PARAMETER mapping database list entry is NULL - @retval EFI_SUCCESS Free success - -**/ -EFI_STATUS -EFIAPI -FreeMappingDatabase ( - IN OUT LIST_ENTRY *MappingDataBase - ) -; - -/** - Read the NV environment variable(s) that contain the override mappings from Controller Device Path to - a set of Driver Device Paths, and create the mapping database in memory to contain these variable info. - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null - @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable - @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted - @retval EFI_SUCCESS Create the mapping database in memory successfully - -**/ -EFI_STATUS -EFIAPI -InitOverridesMapping ( - OUT LIST_ENTRY *MappingDataBase - ) -; - -/** - Save the memory mapping database into NV environment variable(s). - If MappingDataBase list is empty, then delete all platform override NV variables. - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null - @retval EFI_SUCCESS Save memory mapping database successfully - -**/ -EFI_STATUS -EFIAPI -SaveOverridesMapping ( - IN LIST_ENTRY *MappingDataBase - ) -; - -/** - Retrieves the image handle of the platform override driver for a controller in the system from the memory mapping database. - - @param ControllerHandle The device handle of the controller to check if - a driver override exists. - @param DriverImageHandle On output, a pointer to the next driver handle. - Passing in a pointer to NULL, will return the - first driver handle for ControllerHandle. - @param MappingDataBase MappingDataBase - Mapping database list entry - pointer - @param CallerImageHandle The caller driver's image handle, for - UpdateFvFileDevicePath use. - - @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not - a valid handle. Or DriverImagePath is not a - device path that was returned on a previous call - to GetDriverPath(). - @retval EFI_NOT_FOUND A driver override for ControllerHandle was not - found. - @retval EFI_UNSUPPORTED The operation is not supported. - @retval EFI_SUCCESS The driver override for ControllerHandle was - returned in DriverImagePath. - -**/ -EFI_STATUS -EFIAPI -GetDriverFromMapping ( - IN EFI_HANDLE ControllerHandle, - IN OUT EFI_HANDLE *DriverImageHandle, - IN LIST_ENTRY *MappingDataBase, - IN EFI_HANDLE CallerImageHandle - ) -; - -/** - Check mapping database whether already has the mapping info which - records the input Controller to input DriverImage. - - @param ControllerDevicePath The controller device path is to be check. - @param DriverImageDevicePath The driver image device path is to be check. - @param MappingDataBase Mapping database list entry pointer - @param DriverInfoNum the controller's total override driver number - @param DriverImageNO The driver order number for the input DriverImage. - If the DriverImageDevicePath is NULL, DriverImageNO is not set. - - @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL. - @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or - DriverImageDevicePath is not found in the found DriverImage Info list. - @retval EFI_SUCCESS The controller's total override driver number and - input DriverImage's order number is correctly return. -**/ -EFI_STATUS -EFIAPI -CheckMapping ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL, - IN LIST_ENTRY *MappingDataBase, - OUT UINT32 *DriverInfoNum OPTIONAL, - OUT UINT32 *DriverImageNO OPTIONAL - ) -; - -/** - Insert a driver image as a controller's override driver into the mapping database. - The driver image's order number is indicated by DriverImageNO. - - @param ControllerDevicePath The controller device path need to add a - override driver image item - @param DriverImageDevicePath The driver image device path need to be insert - @param MappingDataBase Mapping database list entry pointer - @param DriverImageNO The inserted order number. If this number is taken, - the larger available number will be used. - - @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL - or MappingDataBase is NULL - @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been - recorded into the mapping database. - @retval EFI_SUCCESS The Controller and DriverImage are inserted into - the mapping database successfully. - -**/ -EFI_STATUS -EFIAPI -InsertDriverImage ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, - IN LIST_ENTRY *MappingDataBase, - IN UINT32 DriverImageNO - ) -; - -/** - Delete a controller's override driver from the mapping database. - - @param ControllerDevicePath The controller device path will be deleted - when all drivers images on it are removed. - @param DriverImageDevicePath The driver image device path will be delete. - If NULL, all driver image will be delete. - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL - @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or - DriverImageDevicePath is not found in the found DriverImage Info list. - @retval EFI_SUCCESS Delete the specified driver successfully. - -**/ -EFI_STATUS -EFIAPI -DeleteDriverImage ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, - IN LIST_ENTRY *MappingDataBase - ) -; - -#endif diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf b/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf deleted file mode 100644 index 8514bc2bf0..0000000000 --- a/MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf +++ /dev/null @@ -1,67 +0,0 @@ -#/** @file -# Instance of Platform Driver Override Library to manage driver overriding relationship. -# -# This library instance provides functions to manage the database of overriding relationship -# between controllers and drivers. Each entry of the database contains the mapping that Controller -# Device Path to a set of Driver Device Paths. The database is stored in non-volatile variables. -# -# Copyright (c) 2007 - 2008, Intel Corporation. All rights reserved. -# -# All rights reserved. This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php -# -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# -# -#**/ - -[Defines] - INF_VERSION = 0x00010005 - BASE_NAME = PlatDriOverLib - FILE_GUID = 8bd8d711-2736-46d7-8c81-5de68e0a9e88 - MODULE_TYPE = DXE_DRIVER - VERSION_STRING = 1.0 - LIBRARY_CLASS = PlatformDriverOverrideLib|DXE_DRIVER UEFI_DRIVER UEFI_APPLICATION - -# -# The following information is for reference only and not required by the build tools. -# -# VALID_ARCHITECTURES = IA32 X64 IPF EBC -# - -[Sources.common] - PlatDriOver.h - PlatDriOverLib.c - -[Packages] - MdePkg/MdePkg.dec - MdeModulePkg/MdeModulePkg.dec - -[LibraryClasses] - DxeServicesTableLib - MemoryAllocationLib - DevicePathLib - BaseLib - UefiLib - UefiBootServicesTableLib - UefiRuntimeServicesTableLib - BaseMemoryLib - DebugLib - PrintLib - -[Guids] - ## - # There could be more than one variables, from PlatDriOver, PlatDriOver1, PlatDriOver2,... - # - gEfiOverrideVariableGuid ## CONSUMES ## Variable:L"PlatDriOver" - -[Protocols] - gEfiFirmwareVolume2ProtocolGuid ## CONSUMES - gEfiLoadedImageProtocolGuid ## CONSUMES - gEfiBusSpecificDriverOverrideProtocolGuid ## CONSUMES - gEfiDriverBindingProtocolGuid ## CONSUMES - gEfiDevicePathProtocolGuid ## CONSUMES - gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h deleted file mode 100644 index 7cede71388..0000000000 --- a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOver.h +++ /dev/null @@ -1,195 +0,0 @@ -/** @file - Internal include file for Platform Driver Override Library implementation. - - Copyright (c) 2007 - 2008, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#ifndef _PLAT_DRI_OVER_H_ -#define _PLAT_DRI_OVER_H_ - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - - -#define PLATFORM_OVERRIDE_ITEM_SIGNATURE SIGNATURE_32('p','d','o','i') - typedef struct _PLATFORM_OVERRIDE_ITEM { - UINTN Signature; - LIST_ENTRY Link; - UINT32 DriverInfoNum; - EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; - /// - /// List of DRIVER_IMAGE_INFO - /// - LIST_ENTRY DriverInfoList; - EFI_HANDLE LastReturnedImageHandle; -} PLATFORM_OVERRIDE_ITEM; - -#define DRIVER_IMAGE_INFO_SIGNATURE SIGNATURE_32('p','d','i','i') -typedef struct _DRIVER_IMAGE_INFO { - UINTN Signature; - LIST_ENTRY Link; - EFI_HANDLE ImageHandle; - EFI_DEVICE_PATH_PROTOCOL *DriverImagePath; - BOOLEAN UnLoadable; - BOOLEAN UnStartable; -} DRIVER_IMAGE_INFO; - -#define DEVICE_PATH_STACK_ITEM_SIGNATURE SIGNATURE_32('d','p','s','i') -typedef struct _DEVICE_PATH_STACK_ITEM{ - UINTN Signature; - LIST_ENTRY Link; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; -} DEVICE_PATH_STACK_ITEM; - -/** - Push a controller device path into a globle device path list. - - @param DevicePath The controller device path to push into stack - - @retval EFI_SUCCESS Device path successfully pushed into the stack. - -**/ -EFI_STATUS -EFIAPI -PushDevPathStack ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - -/** - Pop a controller device path from a globle device path list - - @param DevicePath The controller device path popped from stack - - @retval EFI_SUCCESS Controller device path successfully popped. - @retval EFI_NOT_FOUND Stack is empty. - -**/ -EFI_STATUS -EFIAPI -PopDevPathStack ( - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ); - -/** - Check whether a controller device path is in a globle device path list - - @param DevicePath The controller device path to check - - @retval TRUE DevicePath exists in the stack. - @retval FALSE DevicePath does not exist in the stack. - -**/ -BOOLEAN -EFIAPI -CheckExistInStack ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ); - -/** - Update the FV file device path if it is not valid. - - According to a file GUID, check a Fv file device path is valid. If it is invalid, - try to return the valid device path. - FV address maybe changes for memory layout adjust from time to time, use this funciton - could promise the Fv file device path is right. - - @param DevicePath On input, the FV file device path to check - On output, the updated valid FV file device path - @param FileGuid The FV file GUID - @param CallerImageHandle Image handle of the caller - - @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid - parameter - @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file - GUID at all - @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it - is valid - @retval EFI_SUCCESS Successfully updated the invalid DevicePath, - and return the updated device path in DevicePath - -**/ -EFI_STATUS -EFIAPI -UpdateFvFileDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, - IN EFI_GUID *FileGuid, - IN EFI_HANDLE CallerImageHandle - ); - -/** - Gets the data and size of a variable. - - Read the EFI variable (VendorGuid/Name) and return a dynamically allocated - buffer, and the size of the buffer. If failure return NULL. - - @param Name String part of EFI variable name - @param VendorGuid GUID part of EFI variable name - @param VariableSize Returns the size of the EFI variable that was - read - - @return Dynamically allocated memory that contains a copy of the EFI variable. - Caller is responsible freeing the buffer. - @retval NULL Variable was not read - -**/ -VOID * -EFIAPI -GetVariableAndSize ( - IN CHAR16 *Name, - IN EFI_GUID *VendorGuid, - OUT UINTN *VariableSize - ); - -/** - Connect to the handle to a device on the device path. - - This function will create all handles associate with every device - path node. If the handle associate with one device path node can not - be created success, then still give one chance to do the dispatch, - which load the missing drivers if possible. - - @param DevicePathToConnect The device path which will be connected, it can - be a multi-instance device path - - @retval EFI_SUCCESS All handles associate with every device path - node have been created - @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles - @retval EFI_NOT_FOUND Create the handle associate with one device - path node failed - -**/ -EFI_STATUS -EFIAPI -ConnectDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect - ); - -#endif diff --git a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c b/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c deleted file mode 100644 index 006de75ab4..0000000000 --- a/MdeModulePkg/Library/DxePlatDriOverLib/PlatDriOverLib.c +++ /dev/null @@ -1,1870 +0,0 @@ -/** @file - Implementation of Platform Driver Override Library. - - Copyright (c) 2007 - 2008, Intel Corporation - All rights reserved. This program and the accompanying materials - are licensed and made available under the terms and conditions of the BSD License - which accompanies this distribution. The full text of the license may be found at - http://opensource.org/licenses/bsd-license.php - - THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, - WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include "PlatDriOver.h" - -LIST_ENTRY mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack); - -/** - Free all the mapping database memory resource and initialize the mapping list entry. - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_SUCCESS Mapping database successfully freed - @retval EFI_INVALID_PARAMETER MappingDataBase is NULL - -**/ -EFI_STATUS -EFIAPI -FreeMappingDatabase ( - IN OUT LIST_ENTRY *MappingDataBase - ) -{ - LIST_ENTRY *OverrideItemListIndex; - LIST_ENTRY *ImageInfoListIndex; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - DRIVER_IMAGE_INFO *DriverImageInfo; - - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - // - // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[] - // - if (OverrideItem->ControllerDevicePath != NULL){ - FreePool (OverrideItem->ControllerDevicePath); - } - - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - // - // Free DRIVER_IMAGE_INFO.DriverImagePath[] - // - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - if (DriverImageInfo->DriverImagePath != NULL) { - FreePool(DriverImageInfo->DriverImagePath); - } - // - // Free DRIVER_IMAGE_INFO itself - // - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - RemoveEntryList (&DriverImageInfo->Link); - FreePool (DriverImageInfo); - } - // - // Free PLATFORM_OVERRIDE_ITEM itself - // - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - RemoveEntryList (&OverrideItem->Link); - FreePool (OverrideItem); - } - - InitializeListHead (MappingDataBase); - return EFI_SUCCESS; -} - - -/** - Create the mapping database according to variable. - - Read the environment variable(s) that contain the override mappings from Controller Device Path to - a set of Driver Device Paths, and create the mapping database in memory with those variable info. - VariableLayout{ - // - // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load. - // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store - // large mapping infos. - // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, .... - // - UINT32 NotEnd; //Zero is the last one. - // - // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths - // There are often multi mapping entries in a variable. - // - UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i') - UINT32 DriverNum; - EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - ...... - UINT32 NotEnd; //Zero is the last one. - UINT32 SIGNATURE; - UINT32 DriverNum; - EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; - ...... - } - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_SUCCESS Create the mapping database in memory successfully - @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null - @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable - @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted - -**/ -EFI_STATUS -EFIAPI -InitOverridesMapping ( - OUT LIST_ENTRY *MappingDataBase - ) -{ - UINTN BufferSize; - VOID *VariableBuffer; - UINT8 *VariableIndex; - UINTN VariableNum; - CHAR16 OverrideVariableName[40]; - UINT32 NotEnd; - UINT32 DriverNumber; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - DRIVER_IMAGE_INFO *DriverImageInfo; - BOOLEAN Corrupted; - UINT32 Signature; - EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; - EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; - UINTN Index; - - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check the environment variable(s) that contain the override mappings . - // - VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiOverrideVariableGuid, &BufferSize); - ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); - if (VariableBuffer == NULL) { - return EFI_NOT_FOUND; - } - - // - // Traverse all variables. - // - VariableNum = 1; - Corrupted = FALSE; - do { - VariableIndex = VariableBuffer; - // - // End flag - // - NotEnd = *(UINT32*) VariableIndex; - // - // Traverse the entries containing the mapping that Controller Device Path - // to a set of Driver Device Paths within this variable. - // - VariableIndex = VariableIndex + sizeof (UINT32); - while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) { - // - // Check signature of this entry - // - Signature = *(UINT32 *) VariableIndex; - if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) { - Corrupted = TRUE; - break; - } - // - // Create PLATFORM_OVERRIDE_ITEM for this mapping - // - OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM)); - ASSERT (OverrideItem != NULL); - OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE; - InitializeListHead (&OverrideItem->DriverInfoList); - VariableIndex = VariableIndex + sizeof (UINT32); - // - // Get DriverNum - // - DriverNumber = *(UINT32*) VariableIndex; - OverrideItem->DriverInfoNum = DriverNumber; - VariableIndex = VariableIndex + sizeof (UINT32); - // - // Get ControllerDevicePath[] - // - ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex; - OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath); - VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath); - // - // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping() - // - VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); - - // - // Get all DriverImageDevicePath[] - // - for (Index = 0; Index < DriverNumber; Index++) { - // - // Create DRIVER_IMAGE_INFO for this DriverDevicePath[] - // - DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO)); - ASSERT (DriverImageInfo != NULL); - DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE; - - DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex; - DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath); - VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath); - // - // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping() - // - VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); - - InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link); - } - InsertTailList (MappingDataBase, &OverrideItem->Link); - } - - FreePool (VariableBuffer); - if (Corrupted) { - FreeMappingDatabase (MappingDataBase); - return EFI_VOLUME_CORRUPTED; - } - - // - // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them. - // NotEnd indicates whether current variable is the end variable. - // - if (NotEnd != 0) { - UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++); - VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiOverrideVariableGuid, &BufferSize); - ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); - if (VariableBuffer == NULL) { - FreeMappingDatabase (MappingDataBase); - return EFI_VOLUME_CORRUPTED; - } - } - - } while (NotEnd != 0); - - return EFI_SUCCESS; -} - - -/** - Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info. - - @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM - - @return The needed size number - -**/ -UINTN -EFIAPI -GetOneItemNeededSize ( - IN LIST_ENTRY *OverrideItemListIndex - ) -{ - UINTN NeededSize; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - LIST_ENTRY *ImageInfoListIndex; - DRIVER_IMAGE_INFO *DriverImageInfo; - UINTN DevicePathSize; - - NeededSize = 0; - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - NeededSize += sizeof (UINT32); //UINT32 SIGNATURE; - NeededSize += sizeof (UINT32); //UINT32 DriverNum; - DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath); - NeededSize += DevicePathSize; // ControllerDevicePath - // - // Align the controller device path - // - NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1)); - // - // Traverse the Driver Info List of this Override Item - // - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath); - NeededSize += DevicePathSize; //DriverDevicePath - // - // Align the driver image device path - // - NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1)); - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - - return NeededSize; -} - -/** - Deletes all environment variable(s) that contain the override mappings from Controller Device Path to - a set of Driver Device Paths. - - @retval EFI_SUCCESS Delete all variable(s) successfully. - -**/ -EFI_STATUS -EFIAPI -DeleteOverridesVariables ( - VOID - ) -{ - EFI_STATUS Status; - VOID *VariableBuffer; - UINTN VariableNum; - UINTN BufferSize; - UINTN Index; - CHAR16 OverrideVariableName[40]; - - // - // Get environment variable(s) number - // - VariableNum = 0; - VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiOverrideVariableGuid, &BufferSize); - VariableNum++; - if (VariableBuffer == NULL) { - return EFI_NOT_FOUND; - } - // - // Check NotEnd to get all PlatDriOverX variable(s) - // - while ((*(UINT32*)VariableBuffer) != 0) { - UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum); - VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiOverrideVariableGuid, &BufferSize); - VariableNum++; - ASSERT (VariableBuffer != NULL); - } - - // - // Delete PlatDriOver and all additional variables, if exist. - // - Status = gRT->SetVariable ( - L"PlatDriOver", - &gEfiOverrideVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - ASSERT (!EFI_ERROR (Status)); - for (Index = 1; Index < VariableNum; Index++) { - UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index); - Status = gRT->SetVariable ( - OverrideVariableName, - &gEfiOverrideVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - 0, - NULL - ); - ASSERT (!EFI_ERROR (Status)); - } - return EFI_SUCCESS; -} - - -/** - Save the memory mapping database into NV environment variable(s). - - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_SUCCESS Save memory mapping database successfully - @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null - -**/ -EFI_STATUS -EFIAPI -SaveOverridesMapping ( - IN LIST_ENTRY *MappingDataBase - ) -{ - EFI_STATUS Status; - VOID *VariableBuffer; - UINT8 *VariableIndex; - UINTN NumIndex; - CHAR16 OverrideVariableName[40]; - UINT32 NotEnd; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - DRIVER_IMAGE_INFO *DriverImageInfo; - LIST_ENTRY *OverrideItemListIndex; - LIST_ENTRY *ItemIndex; - LIST_ENTRY *ImageInfoListIndex; - UINTN VariableNeededSize; - UINT64 MaximumVariableStorageSize; - UINT64 RemainingVariableStorageSize; - UINT64 MaximumVariableSize; - UINTN OneItemNeededSize; - - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (IsListEmpty (MappingDataBase)) { - Status = DeleteOverridesVariables (); - ASSERT_EFI_ERROR (Status); - return EFI_SUCCESS; - } - - // - // Get the the maximum size of an individual EFI variable in current system - // - gRT->QueryVariableInfo ( - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - &MaximumVariableStorageSize, - &RemainingVariableStorageSize, - &MaximumVariableSize - ); - - NumIndex = 0; - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - // - // Try to find the most proper variable size which <= MaximumVariableSize, - // but can contain mapping info as much as possible - // - VariableNeededSize = sizeof (UINT32); // NotEnd; - ItemIndex = OverrideItemListIndex; - NotEnd = FALSE; - // - // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size. - // - while (!IsNull (MappingDataBase, ItemIndex)) { - OneItemNeededSize = GetOneItemNeededSize (ItemIndex); - // - // If the total size exceeds the MaximumVariableSize, then we must use - // multiple variables. - // - if ((VariableNeededSize + - OneItemNeededSize + - sizeof (VARIABLE_HEADER) + - StrSize (L"PlatDriOver ") - ) >= MaximumVariableSize - ) { - NotEnd = TRUE; - break; - } - - VariableNeededSize += OneItemNeededSize; - ItemIndex = GetNextNode (MappingDataBase, ItemIndex); - } - - if (NotEnd != 0) { - if (VariableNeededSize == sizeof (UINT32)) { - // - // If an individual EFI variable cannot contain a single Item, return error - // - return EFI_OUT_OF_RESOURCES; - } - } - - // - // VariableNeededSize is the most proper variable size, allocate variable buffer - // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize - // - VariableBuffer = AllocateZeroPool (VariableNeededSize); - ASSERT (VariableBuffer != NULL); - ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); - - // - // Fill the variable buffer according to MappingDataBase - // - VariableIndex = VariableBuffer; - *(UINT32 *) VariableIndex = NotEnd; - VariableIndex += sizeof (UINT32); // pass NotEnd - // - // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize - // - while (OverrideItemListIndex != ItemIndex){ - *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE; - VariableIndex += sizeof (UINT32); // pass SIGNATURE - - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum; - VariableIndex += sizeof (UINT32); // pass DriverNum - - CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath)); - VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath - - // - // Align the VariableIndex since the controller device path may not be aligned - // - VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); - // - // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM - // - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath)); - VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath - // - // Align the VariableIndex since the driver image device path may not be aligned - // - VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - } - - ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize); - - if (NumIndex == 0) { - UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver"); - } else { - UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex ); - } - - Status = gRT->SetVariable ( - OverrideVariableName, - &gEfiOverrideVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, - VariableNeededSize, - VariableBuffer - ); - ASSERT (!EFI_ERROR(Status)); - - NumIndex ++; - FreePool (VariableBuffer); - } - - return EFI_SUCCESS; -} - -/** - Get the first Binding protocol which has the specific image handle. - - @param ImageHandle The Image handle - @param BindingHandle The BindingHandle of the found Driver Binding protocol. - If Binding protocol is not found, it is set to NULL. - - @return Pointer into the Binding Protocol interface - @retval NULL The paramter is not valid or the binding protocol is not found. - -**/ -EFI_DRIVER_BINDING_PROTOCOL * -EFIAPI -GetBindingProtocolFromImageHandle ( - IN EFI_HANDLE ImageHandle, - OUT EFI_HANDLE *BindingHandle - ) -{ - EFI_STATUS Status; - UINTN Index; - UINTN DriverBindingHandleCount; - EFI_HANDLE *DriverBindingHandleBuffer; - EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface; - - if (BindingHandle == NULL || ImageHandle == NULL) { - return NULL; - } - // - // Get all drivers which support driver binding protocol - // - DriverBindingHandleCount = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiDriverBindingProtocolGuid, - NULL, - &DriverBindingHandleCount, - &DriverBindingHandleBuffer - ); - if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { - return NULL; - } - - for (Index = 0; Index < DriverBindingHandleCount; Index++) { - DriverBindingInterface = NULL; - Status = gBS->OpenProtocol ( - DriverBindingHandleBuffer[Index], - &gEfiDriverBindingProtocolGuid, - (VOID **) &DriverBindingInterface, - NULL, - NULL, - EFI_OPEN_PROTOCOL_GET_PROTOCOL - ); - if (EFI_ERROR (Status)) { - continue; - } - - if (DriverBindingInterface->ImageHandle == ImageHandle) { - *BindingHandle = DriverBindingHandleBuffer[Index]; - FreePool (DriverBindingHandleBuffer); - return DriverBindingInterface; - } - } - - // - // If no Driver Binding Protocol instance is found - // - FreePool (DriverBindingHandleBuffer); - *BindingHandle = NULL; - return NULL; -} - -/** - Return the current TPL. - - @return Current TPL - -**/ -EFI_TPL -GetCurrentTpl ( - VOID - ) -{ - EFI_TPL Tpl; - - Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); - gBS->RestoreTPL (Tpl); - - return Tpl; -} - - -/** - Retrieves the image handle of the platform override driver for a controller in - the system from the memory mapping database. - - @param ControllerHandle The device handle of the controller to check if - a driver override exists. - @param DriverImageHandle On input, the previously returnd driver image handle. - On output, a pointer to the next driver handle. - Passing in a pointer to NULL, will return the - first driver handle for ControllerHandle. - @param MappingDataBase Mapping database list entry pointer - @param CallerImageHandle The caller driver's image handle, for - UpdateFvFileDevicePath use. - - @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not - a valid handle. Or DriverImagePath is not a - device path that was returned on a previous call - to GetDriverPath(). - @retval EFI_NOT_FOUND A driver override for ControllerHandle was not - found. - @retval EFI_UNSUPPORTED The operation is not supported. - @retval EFI_SUCCESS The driver override for ControllerHandle was - returned in DriverImagePath. - -**/ -EFI_STATUS -EFIAPI -GetDriverFromMapping ( - IN EFI_HANDLE ControllerHandle, - IN OUT EFI_HANDLE *DriverImageHandle, - IN LIST_ENTRY *MappingDataBase, - IN EFI_HANDLE CallerImageHandle - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; - BOOLEAN ControllerFound; - BOOLEAN ImageFound; - EFI_HANDLE *ImageHandleBuffer; - UINTN ImageHandleCount; - UINTN Index; - EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; - EFI_HANDLE DriverBindingHandle; - BOOLEAN FoundLastReturned; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - DRIVER_IMAGE_INFO *DriverImageInfo; - LIST_ENTRY *OverrideItemListIndex; - LIST_ENTRY *ImageInfoListIndex; - EFI_DEVICE_PATH_PROTOCOL *TempDriverImagePath; - EFI_HANDLE ImageHandle; - EFI_HANDLE Handle; - EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; - EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; - UINTN DevicePathSize; - - // - // Check that ControllerHandle is a valid handle - // - if (ControllerHandle == NULL) { - return EFI_INVALID_PARAMETER; - } - // - // Get the device path of ControllerHandle - // - Status = gBS->HandleProtocol ( - ControllerHandle, - &gEfiDevicePathProtocolGuid, - (VOID **) &ControllerDevicePath - ); - if (EFI_ERROR (Status) || ControllerDevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Search ControllerDevicePath in MappingDataBase - // - OverrideItem = NULL; - ControllerFound = FALSE; - DevicePathSize = GetDevicePathSize (ControllerDevicePath); - - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { - if (CompareMem ( - ControllerDevicePath, - OverrideItem->ControllerDevicePath, - DevicePathSize - ) == 0 - ) { - ControllerFound = TRUE; - break; - } - } - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - } - - if (!ControllerFound) { - return EFI_NOT_FOUND; - } - // - // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle. - // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath(). - // - if (*DriverImageHandle != NULL) { - if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) { - return EFI_INVALID_PARAMETER; - } - } - // - // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally, - // so should check whether there is a dead loop. - // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call, - // and check the controller device path whether appear again during the GetDriverPath() call. - // - if (CheckExistInStack (OverrideItem->ControllerDevicePath)) { - // - // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice - // - return EFI_UNSUPPORTED; - } - PushDevPathStack (OverrideItem->ControllerDevicePath); - - // - // Check every override driver, try to load and start them - // - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - if (DriverImageInfo->ImageHandle == NULL) { - // - // Skip if the image is unloadable or unstartable - // - if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) { - TempDriverImagePath = DriverImageInfo->DriverImagePath; - // - // If the image device path contains an FV node, check the FV file device path is valid. - // If it is invalid, try to return the valid device path. - // FV address maybe changes for memory layout adjust from time to time, - // use this funciton could promise the FV file device path is right. - // - Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle); - if (!EFI_ERROR (Status)) { - FreePool (DriverImageInfo->DriverImagePath); - DriverImageInfo->DriverImagePath = TempDriverImagePath; - } - // - // Get all Loaded Image protocol to check whether the driver image has been loaded and started - // - ImageFound = FALSE; - ImageHandleCount = 0; - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiLoadedImageProtocolGuid, - NULL, - &ImageHandleCount, - &ImageHandleBuffer - ); - if (EFI_ERROR (Status) || (ImageHandleCount == 0)) { - return EFI_NOT_FOUND; - } - - for(Index = 0; Index < ImageHandleCount; Index ++) { - // - // Get the EFI Loaded Image Device Path Protocol - // - LoadedImageDevicePath = NULL; - Status = gBS->HandleProtocol ( - ImageHandleBuffer[Index], - &gEfiLoadedImageDevicePathProtocolGuid, - (VOID **) &LoadedImageDevicePath - ); - if (EFI_ERROR (Status)) { - // - // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed. - // - continue; - } - - DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath); - if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) { - if (CompareMem ( - DriverImageInfo->DriverImagePath, - LoadedImageDevicePath, - GetDevicePathSize (LoadedImageDevicePath) - ) == 0 - ) { - ImageFound = TRUE; - break; - } - } - } - - if (ImageFound) { - // - // Find its related driver binding protocol - // Driver binding handle may be different with its driver's Image Handle. - // - DriverBindingHandle = NULL; - DriverBinding = GetBindingProtocolFromImageHandle ( - ImageHandleBuffer[Index], - &DriverBindingHandle - ); - ASSERT (DriverBinding != NULL); - DriverImageInfo->ImageHandle = ImageHandleBuffer[Index]; - } else if (GetCurrentTpl() <= TPL_CALLBACK){ - // - // The driver image has not been loaded and started. Try to load and start it now. - // Try to connect all device in the driver image path. - // - // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but - // since many device need to be connected in CALLBACK level environment( e.g. Usb devices ) - // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit - // to use LoadImage() and StartImage() in CALLBACK TPL. - // - Status = ConnectDevicePath (DriverImageInfo->DriverImagePath); - // - // check whether it points to a PCI Option Rom image, - // and try to use bus override protocol to get its first option rom image driver - // - TempDriverImagePath = DriverImageInfo->DriverImagePath; - gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle); - // - // Get the Bus Specific Driver Override Protocol instance on the Controller Handle - // - Status = gBS->HandleProtocol( - Handle, - &gEfiBusSpecificDriverOverrideProtocolGuid, - (VOID **) &BusSpecificDriverOverride - ); - if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) { - ImageHandle = NULL; - Status = BusSpecificDriverOverride->GetDriver ( - BusSpecificDriverOverride, - &ImageHandle - ); - if (!EFI_ERROR (Status)) { - // - // Find its related driver binding protocol - // Driver binding handle may be different with its driver's Image handle - // - DriverBindingHandle = NULL; - DriverBinding = GetBindingProtocolFromImageHandle ( - ImageHandle, - &DriverBindingHandle - ); - ASSERT (DriverBinding != NULL); - DriverImageInfo->ImageHandle = ImageHandle; - } - } - // - // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver. - // Only file path media or FwVol Device Path Node remain if all device is connected - // - TempDriverImagePath = DriverImageInfo->DriverImagePath; - gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle); - if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) && - (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) || - (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL) - ) { - // - // Try to load the driver - // - TempDriverImagePath = DriverImageInfo->DriverImagePath; - Status = gBS->LoadImage ( - FALSE, - CallerImageHandle, - TempDriverImagePath, - NULL, - 0, - &ImageHandle - ); - if (!EFI_ERROR (Status)) { - // - // Try to start the driver - // - Status = gBS->StartImage (ImageHandle, NULL, NULL); - if (EFI_ERROR (Status)){ - DriverImageInfo->UnStartable = TRUE; - DriverImageInfo->ImageHandle = NULL; - } else { - // - // Find its related driver binding protocol - // Driver binding handle may be different with its driver's Image handle - // - DriverBindingHandle = NULL; - DriverBinding = GetBindingProtocolFromImageHandle ( - ImageHandle, - &DriverBindingHandle - ); - ASSERT (DriverBinding != NULL); - DriverImageInfo->ImageHandle = ImageHandle; - } - } else { - DriverImageInfo->UnLoadable = TRUE; - DriverImageInfo->ImageHandle = NULL; - } - } - } - FreePool (ImageHandleBuffer); - } - } - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - // - // Finish try to load and start the override driver of a controller, popup the controller's device path - // - PopDevPathStack (NULL); - - // - // return the DriverImageHandle for ControllerHandle - // - FoundLastReturned = FALSE; - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - if (DriverImageInfo->ImageHandle != NULL) { - if ((*DriverImageHandle == NULL) || FoundLastReturned) { - // - // If DriverImageHandle is NULL, then we just need to return the first driver. - // If FoundLastReturned, this means we have just encountered the previously returned driver. - // For both cases, we just return the image handle of this driver. - // - OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle; - *DriverImageHandle = DriverImageInfo->ImageHandle; - return EFI_SUCCESS; - } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){ - // - // We have found the previously returned driver. - // - FoundLastReturned = TRUE; - } - } - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - - return EFI_NOT_FOUND; -} - - -/** - Check mapping database whether already has the mapping info which - records the input Controller to input DriverImage. - - @param ControllerDevicePath The controller device path is to be check. - @param DriverImageDevicePath The driver image device path is to be check. - @param MappingDataBase Mapping database list entry pointer - @param DriverInfoNum the controller's total override driver number - @param DriverImageNO The driver order number for the input DriverImage. - If the DriverImageDevicePath is NULL, DriverImageNO is not set. - - @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL. - @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or - DriverImageDevicePath is not found in the found DriverImage Info list. - @retval EFI_SUCCESS The controller's total override driver number and - input DriverImage's order number is correctly return. -**/ -EFI_STATUS -EFIAPI -CheckMapping ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL, - IN LIST_ENTRY *MappingDataBase, - OUT UINT32 *DriverInfoNum OPTIONAL, - OUT UINT32 *DriverImageNO OPTIONAL - ) -{ - LIST_ENTRY *OverrideItemListIndex; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - LIST_ENTRY *ImageInfoListIndex; - DRIVER_IMAGE_INFO *DriverImageInfo; - BOOLEAN Found; - UINT32 ImageNO; - UINTN DevicePathSize; - - if (ControllerDevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Search ControllerDevicePath in MappingDataBase - // - Found = FALSE; - OverrideItem = NULL; - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - DevicePathSize = GetDevicePathSize (ControllerDevicePath); - if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { - if (CompareMem ( - ControllerDevicePath, - OverrideItem->ControllerDevicePath, - DevicePathSize - ) == 0 - ) { - Found = TRUE; - break; - } - } - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - } - - if (!Found) { - // - // ControllerDevicePath is not in MappingDataBase - // - return EFI_NOT_FOUND; - } - - ASSERT (OverrideItem->DriverInfoNum != 0); - if (DriverInfoNum != NULL) { - *DriverInfoNum = OverrideItem->DriverInfoNum; - } - - // - // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath - // in the controller's Driver Image Info List - // - if (DriverImageDevicePath == NULL) { - return EFI_SUCCESS; - } - // - // return the DriverImageHandle for ControllerHandle - // - ImageNO = 0; - Found = FALSE; - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - ImageNO++; - DevicePathSize = GetDevicePathSize (DriverImageDevicePath); - if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) { - if (CompareMem ( - DriverImageDevicePath, - DriverImageInfo->DriverImagePath, - GetDevicePathSize (DriverImageInfo->DriverImagePath) - ) == 0 - ) { - Found = TRUE; - break; - } - } - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - - if (!Found) { - // - // DriverImageDevicePath is not found in the controller's Driver Image Info List - // - return EFI_NOT_FOUND; - } else { - if (DriverImageNO != NULL) { - *DriverImageNO = ImageNO; - } - return EFI_SUCCESS; - } -} - - -/** - Insert a driver image as a controller's override driver into the mapping database. - The driver image's order number is indicated by DriverImageNO. - - @param ControllerDevicePath The controller device path need to add a - override driver image item - @param DriverImageDevicePath The driver image device path need to be insert - @param MappingDataBase Mapping database list entry pointer - @param DriverImageNO The inserted order number. If this number is taken, - the larger available number will be used. - - @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL - or MappingDataBase is NULL - @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been - recorded into the mapping database. - @retval EFI_SUCCESS The Controller and DriverImage are inserted into - the mapping database successfully. - -**/ -EFI_STATUS -EFIAPI -InsertDriverImage ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, - IN LIST_ENTRY *MappingDataBase, - IN UINT32 DriverImageNO - ) -{ - EFI_STATUS Status; - LIST_ENTRY *OverrideItemListIndex; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - LIST_ENTRY *ImageInfoListIndex; - DRIVER_IMAGE_INFO *DriverImageInfo; - BOOLEAN Found; - UINT32 ImageNO; - UINTN DevicePathSize; - - if (ControllerDevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - if (DriverImageDevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // If the driver is already in the controller's Driver Image Info List, - // just return EFI_ALREADY_STARTED. - // - Status = CheckMapping ( - ControllerDevicePath, - DriverImageDevicePath, - MappingDataBase, - NULL, - NULL - ); - if (Status == EFI_SUCCESS) { - return EFI_ALREADY_STARTED; - } - - // - // Search the input ControllerDevicePath in MappingDataBase - // - Found = FALSE; - OverrideItem = NULL; - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - DevicePathSize = GetDevicePathSize (ControllerDevicePath); - if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { - if (CompareMem ( - ControllerDevicePath, - OverrideItem->ControllerDevicePath, - DevicePathSize - ) == 0 - ) { - Found = TRUE; - break; - } - } - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - } - // - // If cannot find, this is a new controller item - // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base - // - if (!Found) { - OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM)); - ASSERT (OverrideItem != NULL); - OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE; - OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath); - InitializeListHead (&OverrideItem->DriverInfoList); - InsertTailList (MappingDataBase, &OverrideItem->Link); - } - - // - // Prepare the driver image related DRIVER_IMAGE_INFO structure. - // - DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO)); - ASSERT (DriverImageInfo != NULL); - DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE; - DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath); - // - // Find the driver image wanted order location - // - ImageNO = 0; - Found = FALSE; - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - if (ImageNO == (DriverImageNO - 1)) { - // - // find the wanted order location, insert it - // - InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link); - OverrideItem->DriverInfoNum ++; - Found = TRUE; - break; - } - ImageNO++; - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - } - - if (!Found) { - // - // if not find the wanted order location, add it as last item of the controller mapping item - // - InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link); - OverrideItem->DriverInfoNum ++; - } - - return EFI_SUCCESS; -} - - -/** - Delete a controller's override driver from the mapping database. - - @param ControllerDevicePath The controller device path will be deleted - when all drivers images on it are removed. - @param DriverImageDevicePath The driver image device path will be delete. - If NULL, all driver image will be delete. - @param MappingDataBase Mapping database list entry pointer - - @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL - @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or - DriverImageDevicePath is not found in the found DriverImage Info list. - @retval EFI_SUCCESS Delete the specified driver successfully. - -**/ -EFI_STATUS -EFIAPI -DeleteDriverImage ( - IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, - IN LIST_ENTRY *MappingDataBase - ) -{ - EFI_STATUS Status; - LIST_ENTRY *OverrideItemListIndex; - PLATFORM_OVERRIDE_ITEM *OverrideItem; - LIST_ENTRY *ImageInfoListIndex; - DRIVER_IMAGE_INFO *DriverImageInfo; - BOOLEAN Found; - UINTN DevicePathSize; - - if (ControllerDevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (MappingDataBase == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND. - // - Status = CheckMapping ( - ControllerDevicePath, - DriverImageDevicePath, - MappingDataBase, - NULL, - NULL - ); - if (EFI_ERROR (Status)) { - return EFI_NOT_FOUND; - } - - // - // Search ControllerDevicePath in MappingDataBase - // - Found = FALSE; - OverrideItem = NULL; - OverrideItemListIndex = GetFirstNode (MappingDataBase); - while (!IsNull (MappingDataBase, OverrideItemListIndex)) { - OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); - DevicePathSize = GetDevicePathSize (ControllerDevicePath); - if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { - if (CompareMem ( - ControllerDevicePath, - OverrideItem->ControllerDevicePath, - DevicePathSize - ) == 0 - ) { - Found = TRUE; - break; - } - } - OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); - } - - ASSERT (Found); - ASSERT (OverrideItem->DriverInfoNum != 0); - - Found = FALSE; - ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); - while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { - DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); - ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); - if (DriverImageDevicePath != NULL) { - // - // Search for the specified DriverImageDevicePath and remove it, then break. - // - DevicePathSize = GetDevicePathSize (DriverImageDevicePath); - if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) { - if (CompareMem ( - DriverImageDevicePath, - DriverImageInfo->DriverImagePath, - GetDevicePathSize (DriverImageInfo->DriverImagePath) - ) == 0 - ) { - Found = TRUE; - FreePool(DriverImageInfo->DriverImagePath); - RemoveEntryList (&DriverImageInfo->Link); - OverrideItem->DriverInfoNum --; - break; - } - } - } else { - // - // Remove all existing driver image info entries, so no break here. - // - Found = TRUE; - FreePool(DriverImageInfo->DriverImagePath); - RemoveEntryList (&DriverImageInfo->Link); - OverrideItem->DriverInfoNum --; - } - } - - // - // Confirm all driver image info entries have been removed, - // if DriverImageDevicePath is NULL. - // - if (DriverImageDevicePath == NULL) { - ASSERT (OverrideItem->DriverInfoNum == 0); - } - // - // If Override Item has no driver image info entry, then delete this item. - // - if (OverrideItem->DriverInfoNum == 0) { - FreePool(OverrideItem->ControllerDevicePath); - RemoveEntryList (&OverrideItem->Link); - FreePool (OverrideItem); - } - - if (!Found) { - // - // DriverImageDevicePath is not NULL and cannot be found in the controller's - // driver image info list. - // - return EFI_NOT_FOUND; - } - - return EFI_SUCCESS; -} - -/** - Push a controller device path into a globle device path list. - - @param DevicePath The controller device path to push into stack - - @retval EFI_SUCCESS Device path successfully pushed into the stack. - -**/ -EFI_STATUS -EFIAPI -PushDevPathStack ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - DEVICE_PATH_STACK_ITEM *DevicePathStackItem; - - DevicePathStackItem = AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM)); - ASSERT (DevicePathStackItem != NULL); - DevicePathStackItem->Signature = DEVICE_PATH_STACK_ITEM_SIGNATURE; - DevicePathStackItem->DevicePath = DuplicateDevicePath (DevicePath); - InsertTailList (&mDevicePathStack, &DevicePathStackItem->Link); - return EFI_SUCCESS; -} - - -/** - Pop a controller device path from a globle device path list - - @param DevicePath The controller device path popped from stack - - @retval EFI_SUCCESS Controller device path successfully popped. - @retval EFI_NOT_FOUND Stack is empty. - -**/ -EFI_STATUS -EFIAPI -PopDevPathStack ( - OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath - ) -{ - DEVICE_PATH_STACK_ITEM *DevicePathStackItem; - LIST_ENTRY *ItemListIndex; - - ItemListIndex = mDevicePathStack.BackLink; - // - // Check if the stack is empty - // - if (ItemListIndex != &mDevicePathStack){ - DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE); - if (DevicePath != NULL) { - *DevicePath = DuplicateDevicePath (DevicePathStackItem->DevicePath); - } - FreePool (DevicePathStackItem->DevicePath); - RemoveEntryList (&DevicePathStackItem->Link); - FreePool (DevicePathStackItem); - return EFI_SUCCESS; - } - return EFI_NOT_FOUND; -} - - -/** - Check whether a controller device path is in a globle device path list - - @param DevicePath The controller device path to check - - @retval TRUE DevicePath exists in the stack. - @retval FALSE DevicePath does not exist in the stack. - -**/ -BOOLEAN -EFIAPI -CheckExistInStack ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePath - ) -{ - DEVICE_PATH_STACK_ITEM *DevicePathStackItem; - LIST_ENTRY *ItemListIndex; - UINTN DevicePathSize; - - ItemListIndex = mDevicePathStack.BackLink; - while (ItemListIndex != &mDevicePathStack){ - DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE); - DevicePathSize = GetDevicePathSize (DevicePath); - if (DevicePathSize == GetDevicePathSize (DevicePathStackItem->DevicePath)) { - if (CompareMem (DevicePath, DevicePathStackItem->DevicePath, DevicePathSize) == 0) { - return TRUE; - } - } - ItemListIndex = ItemListIndex->BackLink; - } - - return FALSE; -} - - -/** - Update the FV file device path if it is not valid. - - According to a file GUID, check a Fv file device path is valid. If it is invalid, - try to return the valid device path. - FV address maybe changes for memory layout adjust from time to time, use this funciton - could promise the Fv file device path is right. - - @param DevicePath On input, the FV file device path to check - On output, the updated valid FV file device path - @param FileGuid The FV file GUID - @param CallerImageHandle Image handle of the caller - - @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid - parameter - @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file - GUID at all - @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it - is valid - @retval EFI_SUCCESS Successfully updated the invalid DevicePath, - and return the updated device path in DevicePath - -**/ -EFI_STATUS -EFIAPI -UpdateFvFileDevicePath ( - IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, - IN EFI_GUID *FileGuid, - IN EFI_HANDLE CallerImageHandle - ) -{ - EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; - EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; - EFI_STATUS Status; - EFI_GUID *GuidPoint; - UINTN Index; - UINTN FvHandleCount; - EFI_HANDLE *FvHandleBuffer; - EFI_FV_FILETYPE Type; - UINTN Size; - EFI_FV_FILE_ATTRIBUTES Attributes; - UINT32 AuthenticationStatus; - BOOLEAN FindFvFile; - EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; - EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; - MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode; - EFI_HANDLE FoundFvHandle; - EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; - BOOLEAN HasFvNode; - - if (DevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (*DevicePath == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Check whether the device path points to the default the input FV file - // - TempDevicePath = *DevicePath; - LastDeviceNode = TempDevicePath; - while (!IsDevicePathEnd (TempDevicePath)) { - LastDeviceNode = TempDevicePath; - TempDevicePath = NextDevicePathNode (TempDevicePath); - } - GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode); - if (GuidPoint == NULL) { - // - // If this option does not point to a FV file, just return EFI_UNSUPPORTED. - // - return EFI_UNSUPPORTED; - } - - if (FileGuid != NULL) { - if (!CompareGuid (GuidPoint, FileGuid)) { - // - // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED - // - return EFI_UNSUPPORTED; - } - } else { - FileGuid = GuidPoint; - } - - // - // Check to see if the device path contains memory map node - // - TempDevicePath = *DevicePath; - HasFvNode = FALSE; - while (!IsDevicePathEnd (TempDevicePath)) { - // - // Use old Device Path - // - if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH && - DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) { - HasFvNode = TRUE; - break; - } - TempDevicePath = NextDevicePathNode (TempDevicePath); - } - - if (!HasFvNode) { - return EFI_UNSUPPORTED; - } - - // - // Check whether the input Fv file device path is valid - // - TempDevicePath = *DevicePath; - FoundFvHandle = NULL; - Status = gBS->LocateDevicePath ( - &gEfiFirmwareVolume2ProtocolGuid, - &TempDevicePath, - &FoundFvHandle - ); - if (!EFI_ERROR (Status)) { - Status = gBS->HandleProtocol ( - FoundFvHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &Fv - ); - if (!EFI_ERROR (Status)) { - // - // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there - // - Status = Fv->ReadFile ( - Fv, - FileGuid, - NULL, - &Size, - &Type, - &Attributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - return EFI_ALREADY_STARTED; - } - } - } - - // - // Look for the input wanted FV file in current FV - // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV - // - FindFvFile = FALSE; - FoundFvHandle = NULL; - Status = gBS->HandleProtocol ( - CallerImageHandle, - &gEfiLoadedImageProtocolGuid, - (VOID **) &LoadedImage - ); - if (!EFI_ERROR (Status)) { - Status = gBS->HandleProtocol ( - LoadedImage->DeviceHandle, - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &Fv - ); - if (!EFI_ERROR (Status)) { - Status = Fv->ReadFile ( - Fv, - FileGuid, - NULL, - &Size, - &Type, - &Attributes, - &AuthenticationStatus - ); - if (!EFI_ERROR (Status)) { - FindFvFile = TRUE; - FoundFvHandle = LoadedImage->DeviceHandle; - } - } - } - // - // Second, if fail to find, try to enumerate all FV - // - if (!FindFvFile) { - gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolume2ProtocolGuid, - NULL, - &FvHandleCount, - &FvHandleBuffer - ); - for (Index = 0; Index < FvHandleCount; Index++) { - gBS->HandleProtocol ( - FvHandleBuffer[Index], - &gEfiFirmwareVolume2ProtocolGuid, - (VOID **) &Fv - ); - - Status = Fv->ReadFile ( - Fv, - FileGuid, - NULL, - &Size, - &Type, - &Attributes, - &AuthenticationStatus - ); - if (EFI_ERROR (Status)) { - // - // Skip if input Fv file not in the FV - // - continue; - } - FindFvFile = TRUE; - FoundFvHandle = FvHandleBuffer[Index]; - break; - } - } - - if (FindFvFile) { - // - // Build the shell device path - // - NewDevicePath = DevicePathFromHandle (FoundFvHandle); - EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid); - NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode); - *DevicePath = NewDevicePath; - return EFI_SUCCESS; - } - return EFI_NOT_FOUND; -} - - -/** - Gets the data and size of a variable. - - Read the EFI variable (VendorGuid/Name) and return a dynamically allocated - buffer, and the size of the buffer. If failure return NULL. - - @param Name String part of EFI variable name - @param VendorGuid GUID part of EFI variable name - @param VariableSize Returns the size of the EFI variable that was - read - - @return Dynamically allocated memory that contains a copy of the EFI variable. - Caller is responsible freeing the buffer. - @retval NULL Variable was not read - -**/ -VOID * -EFIAPI -GetVariableAndSize ( - IN CHAR16 *Name, - IN EFI_GUID *VendorGuid, - OUT UINTN *VariableSize - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - VOID *Buffer; - - Buffer = NULL; - - // - // Pass in a zero size buffer to find the required buffer size. - // - BufferSize = 0; - Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); - if (Status == EFI_BUFFER_TOO_SMALL) { - // - // Allocate the buffer to return - // - Buffer = AllocateZeroPool (BufferSize); - if (Buffer == NULL) { - return NULL; - } - // - // Read variable into the allocated buffer. - // - Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); - if (EFI_ERROR (Status)) { - BufferSize = 0; - } - } - - *VariableSize = BufferSize; - return Buffer; -} - - -/** - Connect to the handle to a device on the device path. - - This function will create all handles associate with every device - path node. If the handle associate with one device path node can not - be created success, then still give one chance to do the dispatch, - which load the missing drivers if possible. - - @param DevicePathToConnect The device path which will be connected, it can - be a multi-instance device path - - @retval EFI_SUCCESS All handles associate with every device path - node have been created - @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles - @retval EFI_NOT_FOUND Create the handle associate with one device - path node failed - -**/ -EFI_STATUS -EFIAPI -ConnectDevicePath ( - IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH_PROTOCOL *DevicePath; - EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; - EFI_DEVICE_PATH_PROTOCOL *Instance; - EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; - EFI_DEVICE_PATH_PROTOCOL *Next; - EFI_HANDLE Handle; - EFI_HANDLE PreviousHandle; - UINTN Size; - - if (DevicePathToConnect == NULL) { - return EFI_SUCCESS; - } - - DevicePath = DuplicateDevicePath (DevicePathToConnect); - CopyOfDevicePath = DevicePath; - if (DevicePath == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - do { - // - // The outer loop handles multi instance device paths. - // Only console variables contain multiple instance device paths. - // - // After this call DevicePath points to the next Instance - // - Instance = GetNextDevicePathInstance (&DevicePath, &Size); - ASSERT (Instance != NULL); - - Next = Instance; - while (!IsDevicePathEndType (Next)) { - Next = NextDevicePathNode (Next); - } - - SetDevicePathEndNode (Next); - - // - // Start the real work of connect with RemainingDevicePath - // - PreviousHandle = NULL; - do { - // - // Find the handle that best matches the Device Path. If it is only a - // partial match the remaining part of the device path is returned in - // RemainingDevicePath. - // - RemainingDevicePath = Instance; - Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); - - if (!EFI_ERROR (Status)) { - if (Handle == PreviousHandle) { - // - // If no forward progress is made try invoking the Dispatcher. - // A new FV may have been added to the system an new drivers - // may now be found. - // Status == EFI_SUCCESS means a driver was dispatched - // Status == EFI_NOT_FOUND means no new drivers were dispatched - // - Status = gDS->Dispatch (); - } - - if (!EFI_ERROR (Status)) { - PreviousHandle = Handle; - // - // Connect all drivers that apply to Handle and RemainingDevicePath, - // the Recursive flag is FALSE so only one level will be expanded. - // - // Do not check the connect status here, if the connect controller fail, - // then still give the chance to do dispatch, because partial - // RemainingDevicepath may be in the new FV - // - // 1. If the connect fails, RemainingDevicepath and handle will not - // change, so next time will do the dispatch, then dispatch's status - // will take effect - // 2. If the connect succeeds, the RemainingDevicepath and handle will - // change, then avoid the dispatch, we have chance to continue the - // next connection - // - gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); - } - } - // - // Loop until RemainingDevicePath is an empty device path - // - } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); - - } while (DevicePath != NULL); - - if (CopyOfDevicePath != NULL) { - FreePool (CopyOfDevicePath); - } - // - // All handle with DevicePath exists in the handle database - // - return Status; -} diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec index 351748244c..3c63b4cdae 100644 --- a/MdeModulePkg/MdeModulePkg.dec +++ b/MdeModulePkg/MdeModulePkg.dec @@ -50,10 +50,6 @@ ## @libraryclass Defines a set of methods related recovery mode. RecoveryLib|Include/Library/RecoveryLib.h - ## @libraryclass Basic platform driver override functions. - # This library is only intended to be used by Platform Driver Override Dxe Driver and Application. - PlatformDriverOverrideLib|Include/Library/PlatformDriverOverrideLib.h - ## @libraryclass Provides HII related functions. HiiLib|Include/Library/HiiLib.h @@ -121,10 +117,6 @@ ## Include/Guid/VariableFormat.h gEfiVariableGuid = { 0xddcf3616, 0x3275, 0x4164, { 0x98, 0xb6, 0xfe, 0x85, 0x70, 0x7f, 0xfe, 0x7d }} - ## Platform Override Variable guid - ## Include/Guid/OverrideVariable.h - gEfiOverrideVariableGuid = { 0x8e3d4ad5, 0xf762, 0x438a, { 0xa1, 0xc1, 0x5b, 0x9f, 0xe6, 0x8c, 0x6b, 0x15 }} - ## Performance protocol guid that also acts as the performance HOB guid and performance variable GUID ## Include/Guid/Performance.h gPerformanceProtocolGuid = { 0x76B6BDFA, 0x2ACD, 0x4462, { 0x9E, 0x3F, 0xCB, 0x58, 0xC9, 0x69, 0xD9, 0x37 }} diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 065121dffd..f338a9ac50 100644 --- a/MdeModulePkg/MdeModulePkg.dsc +++ b/MdeModulePkg/MdeModulePkg.dsc @@ -71,7 +71,6 @@ CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf - PlatformDriverOverrideLib|MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf ReportStatusCodeLib|MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.inf MemoryTestLib|MdeModulePkg/Library/BaseMemoryTestLibNull/BaseMemoryTestLibNull.inf @@ -271,7 +270,6 @@ MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf MdeModulePkg/Library/DxePerformanceLib/DxePerformanceLib.inf - MdeModulePkg/Library/DxePlatDriOverLib/DxePlatDriOverLib.inf MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf MdeModulePkg/Library/DxePrintLibPrint2Protocol/DxePrintLibPrint2Protocol.inf MdeModulePkg/Library/PeiPerformanceLib/PeiPerformanceLib.inf @@ -315,7 +313,6 @@ MdeModulePkg/Universal/PCD/Dxe/Pcd.inf MdeModulePkg/Universal/PCD/Pei/Pcd.inf MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf - MdeModulePkg/Application/PlatOverMngr/PlatOverMngr.inf MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf MdeModulePkg/Application/VariableInfo/VariableInfo.inf diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h new file mode 100644 index 0000000000..efd87e91e7 --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/InternalPlatDriOverrideDxe.h @@ -0,0 +1,218 @@ +/** @file + Ihe internal heder file includes the required Protocol/Guid/Library + and the shared function APIs. + +Copyright (c) 2007 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _INTERNAL_PLATFORM_DRIVER_OVERRIDE_H_ +#define _INTERNAL_PLATFORM_DRIVER_OVERRIDE_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + Free all the mapping database memory resource and initialize the mapping list entry. + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_INVALID_PARAMETER mapping database list entry is NULL + @retval EFI_SUCCESS Free success + +**/ +EFI_STATUS +EFIAPI +FreeMappingDatabase ( + IN OUT LIST_ENTRY *MappingDataBase + ) +; + +/** + Read the NV environment variable(s) that contain the override mappings from Controller Device Path to + a set of Driver Device Paths, and create the mapping database in memory to contain these variable info. + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null + @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable + @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted + @retval EFI_SUCCESS Create the mapping database in memory successfully + +**/ +EFI_STATUS +EFIAPI +InitOverridesMapping ( + OUT LIST_ENTRY *MappingDataBase + ) +; + +/** + Save the memory mapping database into NV environment variable(s). + If MappingDataBase list is empty, then delete all platform override NV variables. + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null + @retval EFI_SUCCESS Save memory mapping database successfully + +**/ +EFI_STATUS +EFIAPI +SaveOverridesMapping ( + IN LIST_ENTRY *MappingDataBase + ) +; + +/** + Retrieves the image handle of the platform override driver for a controller in the system from the memory mapping database. + + @param ControllerHandle The device handle of the controller to check if + a driver override exists. + @param DriverImageHandle On output, a pointer to the next driver handle. + Passing in a pointer to NULL, will return the + first driver handle for ControllerHandle. + @param MappingDataBase MappingDataBase - Mapping database list entry + pointer + @param CallerImageHandle The caller driver's image handle, for + UpdateFvFileDevicePath use. + + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not + a valid handle. Or DriverImagePath is not a + device path that was returned on a previous call + to GetDriverPath(). + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not + found. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SUCCESS The driver override for ControllerHandle was + returned in DriverImagePath. + +**/ +EFI_STATUS +EFIAPI +GetDriverFromMapping ( + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE *DriverImageHandle, + IN LIST_ENTRY *MappingDataBase, + IN EFI_HANDLE CallerImageHandle + ) +; + +/** + Check mapping database whether already has the mapping info which + records the input Controller to input DriverImage. + + @param ControllerDevicePath The controller device path is to be check. + @param DriverImageDevicePath The driver image device path is to be check. + @param MappingDataBase Mapping database list entry pointer + @param DriverInfoNum the controller's total override driver number + @param DriverImageNO The driver order number for the input DriverImage. + If the DriverImageDevicePath is NULL, DriverImageNO is not set. + + @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL. + @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or + DriverImageDevicePath is not found in the found DriverImage Info list. + @retval EFI_SUCCESS The controller's total override driver number and + input DriverImage's order number is correctly return. +**/ +EFI_STATUS +EFIAPI +CheckMapping ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL, + IN LIST_ENTRY *MappingDataBase, + OUT UINT32 *DriverInfoNum OPTIONAL, + OUT UINT32 *DriverImageNO OPTIONAL + ) +; + +/** + Insert a driver image as a controller's override driver into the mapping database. + The driver image's order number is indicated by DriverImageNO. + + @param ControllerDevicePath The controller device path need to add a + override driver image item + @param DriverImageDevicePath The driver image device path need to be insert + @param MappingDataBase Mapping database list entry pointer + @param DriverImageNO The inserted order number. If this number is taken, + the larger available number will be used. + + @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL + or MappingDataBase is NULL + @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been + recorded into the mapping database. + @retval EFI_SUCCESS The Controller and DriverImage are inserted into + the mapping database successfully. + +**/ +EFI_STATUS +EFIAPI +InsertDriverImage ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, + IN LIST_ENTRY *MappingDataBase, + IN UINT32 DriverImageNO + ) +; + +/** + Delete a controller's override driver from the mapping database. + + @param ControllerDevicePath The controller device path will be deleted + when all drivers images on it are removed. + @param DriverImageDevicePath The driver image device path will be delete. + If NULL, all driver image will be delete. + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL + @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or + DriverImageDevicePath is not found in the found DriverImage Info list. + @retval EFI_SUCCESS Delete the specified driver successfully. + +**/ +EFI_STATUS +EFIAPI +DeleteDriverImage ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, + IN LIST_ENTRY *MappingDataBase + ) +; + +#endif diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c new file mode 100644 index 0000000000..47921cd43b --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideDxe.c @@ -0,0 +1,1667 @@ +/** @file + This file also installs UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL. + + The main code offers a UI interface in device manager to let user configure + platform override protocol to override the default algorithm for matching + drivers to controllers. + + The main flow: + 1. It dynamicly locate all controller device path. + 2. It dynamicly locate all drivers which support binding protocol. + 3. It export and dynamicly update two menu to let user select the + mapping between drivers to controllers. + 4. It save all the mapping info in NV variables which will be consumed + by platform override protocol driver to publish the platform override protocol. + +Copyright (c) 2007 - 2009, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalPlatDriOverrideDxe.h" +#include "PlatOverMngr.h" + +#define EFI_CALLBACK_INFO_SIGNATURE SIGNATURE_32 ('C', 'l', 'b', 'k') +#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, ConfigAccess, EFI_CALLBACK_INFO_SIGNATURE) + +typedef struct { + UINTN Signature; + EFI_HANDLE DriverHandle; + EFI_HII_HANDLE RegisteredHandle; + PLAT_OVER_MNGR_DATA FakeNvData; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL PlatformDriverOverride; +} EFI_CALLBACK_INFO; + +#pragma pack(1) + +/// +/// HII specific Vendor Device Path definition. +/// +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +#pragma pack() + +// +// uni string and Vfr Binary data. +// +extern UINT8 VfrBin[]; +extern UINT8 PlatDriOverrideDxeStrings[]; + +// +// module global data +// +EFI_GUID mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID; +CHAR16 mVariableName[] = L"Data"; +LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase); +BOOLEAN mEnvironmentVariableRead = FALSE; +EFI_HANDLE mCallerImageHandle = NULL; + +EFI_HANDLE *mDevicePathHandleBuffer; +EFI_HANDLE *mDriverImageHandleBuffer; + +INTN mSelectedCtrIndex; +EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM]; +UINTN mDriverImageHandleCount; +EFI_STRING_ID mDriverImageToken[MAX_CHOICE_NUM]; +EFI_STRING_ID mDriverImageFilePathToken[MAX_CHOICE_NUM]; +EFI_LOADED_IMAGE_PROTOCOL *mDriverImageProtocol[MAX_CHOICE_NUM]; +EFI_DEVICE_PATH_PROTOCOL *mControllerDevicePathProtocol[MAX_CHOICE_NUM]; +UINTN mSelectedDriverImageNum; +UINTN mLastSavedDriverImageNum; +UINT16 mCurrentPage; +EFI_CALLBACK_INFO *mCallbackInfo; + +HII_VENDOR_DEVICE_PATH mHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + EFI_CALLER_ID_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + +/** + Converting a given device to an unicode string. + + This function will dependent on gEfiDevicePathToTextProtocolGuid, if protocol + does not installed, then return unknown device path L"?" directly. + + @param DevPath Given device path instance + + @return Converted string from given device path. + @retval L"?" Can not locate gEfiDevicePathToTextProtocolGuid protocol for converting. +**/ +CHAR16 * +DevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + CHAR16 *ToText; + + if (DevPath == NULL) { + return L""; + } + + Status = gBS->LocateProtocol ( + &gEfiDevicePathToTextProtocolGuid, + NULL, + (VOID **) &DevPathToText + ); + if (!EFI_ERROR (Status)) { + ToText = DevPathToText->ConvertDevicePathToText ( + DevPath, + FALSE, + TRUE + ); + ASSERT (ToText != NULL); + return ToText; + } + + return L"?"; +} + +/** + Worker function to get the driver name by ComponentName or ComponentName2 protocol + according to the driver binding handle. + + @param DriverBindingHandle The Handle of DriverBinding. + @param ProtocolGuid The pointer to Component Name (2) protocol GUID. + @param VariableName The name of the RFC 4646 or ISO 639-2 language variable. + + @retval !NULL Pointer into the image name if the image name is found, + @retval NULL Pointer to NULL if the image name is not found. + +**/ +CHAR16 * +GetComponentNameWorker ( + IN EFI_HANDLE DriverBindingHandle, + IN EFI_GUID *ProtocolGuid, + IN CONST CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + EFI_COMPONENT_NAME_PROTOCOL *ComponentName; + CHAR16 *DriverName; + CHAR8 *Language; + CHAR8 *BestLanguage; + + Status = gBS->OpenProtocol ( + DriverBindingHandle, + ProtocolGuid, + (VOID *) &ComponentName, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + // + // Find the best matching language. + // + Language = GetEfiGlobalVariable (VariableName); + BestLanguage = GetBestLanguage ( + ComponentName->SupportedLanguages, + (BOOLEAN) (ProtocolGuid == &gEfiComponentNameProtocolGuid), + Language, + NULL + ); + + DriverName = NULL; + if (BestLanguage != NULL) { + ComponentName->GetDriverName ( + ComponentName, + BestLanguage, + &DriverName + ); + FreePool (BestLanguage); + } + + if (Language != NULL) { + FreePool (Language); + } + + return DriverName; +} + + +/** + Get the driver name by ComponentName or ComponentName2 protocol + according to the driver binding handle + + @param DriverBindingHandle The Handle of DriverBinding. + + @retval !NULL Pointer into the image name if the image name is found, + @retval NULL Pointer to NULL if the image name is not found. + +**/ +CHAR16 * +GetComponentName ( + IN EFI_HANDLE DriverBindingHandle + ) +{ + CHAR16 *DriverName; + + // + // Try RFC 4646 Component Name 2 protocol first. + // + DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentName2ProtocolGuid, L"PlatformLang"); + if (DriverName == NULL) { + // + // If we can not get driver name from Component Name 2 protocol, we can try ISO 639-2 Component Name protocol. + // + DriverName = GetComponentNameWorker (DriverBindingHandle, &gEfiComponentNameProtocolGuid, L"Lang"); + } + + return DriverName; +} + +/** + Get the image name from EFI UI section. + Get FV protocol by its loaded image protocol to abstract EFI UI section. + + @param Image Pointer to the loaded image protocol + + @retval !NULL Pointer to the image name if the image name is found, + @retval NULL NULL if the image name is not found. + +**/ +CHAR16 * +GetImageName ( + IN EFI_LOADED_IMAGE_PROTOCOL *Image + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + EFI_DEVICE_PATH_PROTOCOL *AlignedDevPathNode; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + VOID *Buffer; + UINTN BufferSize; + UINT32 AuthenticationStatus; + EFI_GUID *NameGuid; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv2; + + Fv2 = NULL; + Buffer = NULL; + BufferSize = 0; + + if (Image->FilePath == NULL) { + return NULL; + } + DevPathNode = Image->FilePath; + + while (!IsDevicePathEnd (DevPathNode)) { + // + // Make sure device path node is aligned when accessing it's FV Name Guid field. + // + AlignedDevPathNode = AllocateCopyPool (DevicePathNodeLength(DevPathNode), DevPathNode); + + // + // Find the Fv File path + // + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)AlignedDevPathNode); + if (NameGuid != NULL) { + FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) AlignedDevPathNode; + Status = gBS->HandleProtocol ( + Image->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv2 + ); + // + // Locate Image EFI UI section to get the image name. + // + if (!EFI_ERROR (Status)) { + Status = Fv2->ReadSection ( + Fv2, + &FvFilePath->FvFileName, + EFI_SECTION_USER_INTERFACE, + 0, + &Buffer, + &BufferSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + FreePool (AlignedDevPathNode); + break; + } + Buffer = NULL; + } + } + + FreePool (AlignedDevPathNode); + + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + + return Buffer; +} + +/** + Prepare the first page to let user select the device controller which need to + add mapping drivers if user select 'Refresh' in first page. + During first page, user will see all currnet controller device path in system, + select any device path will go to second page to select its overrides drivers. + + @param Private Pointer to EFI_CALLBACK_INFO. + @param KeyValue The callback key value of device controller item in first page. + @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +UpdateDeviceSelectPage ( + IN EFI_CALLBACK_INFO *Private, + IN UINT16 KeyValue, + IN PLAT_OVER_MNGR_DATA *FakeNvData + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN DevicePathHandleCount; + CHAR16 *NewString; + EFI_STRING_ID NewStringToken; + CHAR16 *ControllerName; + EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + UINTN Len; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Set current page form ID. + // + mCurrentPage = FORM_ID_DEVICE; + + // + // Initial the mapping database in memory + // + FreeMappingDatabase (&mMappingDataBase); + InitOverridesMapping (&mMappingDataBase); + + // + // Init OpCode Handle + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = FORM_ID_DEVICE; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Clear first page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_DEVICE, + StartOpCodeHandle, // Label FORM_ID_DEVICE + EndOpCodeHandle // LABEL_END + ); + + // + // When user enter the page at first time, the 'first refresh' string is given to notify user to refresh all the drivers, + // then the 'first refresh' string will be replaced by the 'refresh' string, and the two strings content are same after the replacement + // + NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH); + NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), NULL); + ASSERT (NewString != NULL); + if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) { + ASSERT (FALSE); + } + FreePool (NewString); + + NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP); + NewString = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), NULL); + ASSERT (NewString != NULL); + if (HiiSetString (Private->RegisteredHandle, NewStringToken, NewString, NULL) == 0) { + ASSERT (FALSE); + } + FreePool (NewString); + + // + // created needed controller device item in first page + // + DevicePathHandleCount = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &DevicePathHandleCount, + &mDevicePathHandleBuffer + ); + if (EFI_ERROR (Status) || (DevicePathHandleCount == 0)) { + return EFI_SUCCESS; + } + + for (Index = 0; Index < DevicePathHandleCount; Index++) { + if (FakeNvData->PciDeviceFilter == 0x01) { + // + // Only care PCI device which contain efi driver in its option rom. + // + + // + // Check whether it is a pci device + // + ControllerDevicePath = NULL; + Status = gBS->OpenProtocol ( + mDevicePathHandleBuffer[Index], + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + // + // Check whether it contain efi driver in its option rom + // + Status = gBS->HandleProtocol( + mDevicePathHandleBuffer[Index], + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID **) &BusSpecificDriverOverride + ); + if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { + continue; + } + } + + ControllerDevicePath = NULL; + Status = gBS->OpenProtocol ( + mDevicePathHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ControllerDevicePath, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + // + // Save the device path protocol interface + // + mControllerDevicePathProtocol[Index] = ControllerDevicePath; + + // + // Get the driver name + // + ControllerName = DevicePathToStr (ControllerDevicePath); + + // + // Export the driver name string and create item in set options page + // + Len = StrSize (ControllerName); + NewString = AllocateZeroPool (Len + StrSize (L"--")); + ASSERT (NewString != NULL); + if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) { + StrCat (NewString, L"--"); + } else { + StrCat (NewString, L"**"); + } + StrCat (NewString, ControllerName); + + NewStringToken = HiiSetString (Private->RegisteredHandle, mControllerToken[Index], NewString, NULL); + ASSERT (NewStringToken != 0); + FreePool (NewString); + // + // Save the device path string toke for next access use + // + mControllerToken[Index] = NewStringToken; + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + FORM_ID_DRIVER, + NewStringToken, + STRING_TOKEN (STR_GOTO_HELP_DRIVER), + EFI_IFR_FLAG_CALLBACK, + (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET) + ); + } + + // + // Update first page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_DEVICE, + StartOpCodeHandle, // Label FORM_ID_DEVICE + EndOpCodeHandle // LABEL_END + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + + return EFI_SUCCESS; +} + +/** + Get the first Driver Binding handle which has the specific image handle. + + @param ImageHandle The Image handle + + @return Handle to Driver binding + @retval NULL The paramter is not valid or the driver binding handle is not found. + +**/ +EFI_HANDLE +GetDriverBindingHandleFromImageHandle ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface; + EFI_HANDLE DriverBindingHandle; + + DriverBindingHandle = NULL; + + if (ImageHandle == NULL) { + return NULL; + } + // + // Get all drivers which support driver binding protocol + // + DriverBindingHandleCount = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { + return NULL; + } + + // + // Get the first Driver Binding handle which has the specific image handle. + // + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + DriverBindingInterface = NULL; + Status = gBS->OpenProtocol ( + DriverBindingHandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBindingInterface, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (DriverBindingInterface->ImageHandle == ImageHandle) { + DriverBindingHandle = DriverBindingHandleBuffer[Index]; + break; + } + } + + FreePool (DriverBindingHandleBuffer); + return DriverBindingHandle; +} + +/** + Prepare to let user select the drivers which need mapping with the device controller + selected in first page. + + @param Private Pointer to EFI_CALLBACK_INFO. + @param KeyValue The callback key value of device controller item in first page. + KeyValue is larger than or equal to KEY_VALUE_DEVICE_OFFSET. + @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +UpdateBindingDriverSelectPage ( + IN EFI_CALLBACK_INFO *Private, + IN UINT16 KeyValue, + IN PLAT_OVER_MNGR_DATA *FakeNvData + ) +{ + EFI_STATUS Status; + UINTN Index; + CHAR16 *NewString; + EFI_STRING_ID NewStringToken; + EFI_STRING_ID NewStringHelpToken; + UINTN DriverImageHandleCount; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + CHAR16 *DriverName; + BOOLEAN FreeDriverName; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + EFI_HANDLE DriverBindingHandle; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // If user select a controller item in the first page the following code will be run. + // During second page, user will see all currnet driver bind protocol driver, the driver name and its device path will be shown + // + //First acquire the list of Loaded Image Protocols, and then when want the name of the driver, look up all the Driver Binding Protocols + // and find the first one whose ImageHandle field matches the image handle of the Loaded Image Protocol. + // 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. + // + + mCurrentPage = FORM_ID_DRIVER; + // + // Switch the item callback key value to its NO. in mDevicePathHandleBuffer + // + mSelectedCtrIndex = KeyValue - KEY_VALUE_DEVICE_OFFSET; + ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM); + + mLastSavedDriverImageNum = 0; + + // + // Init OpCode Handle + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = FORM_ID_DRIVER; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Clear second page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_DRIVER, + StartOpCodeHandle, + EndOpCodeHandle + ); + + // + // Show all driver which support loaded image protocol in second page + // + DriverImageHandleCount = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadedImageProtocolGuid, + NULL, + &DriverImageHandleCount, + &mDriverImageHandleBuffer + ); + if (EFI_ERROR (Status) || (DriverImageHandleCount == 0)) { + return EFI_NOT_FOUND; + } + + mDriverImageHandleCount = DriverImageHandleCount; + for (Index = 0; Index < DriverImageHandleCount; Index++) { + // + // Step1: Get the driver image total file path for help string and the driver name. + // + + // + // Find driver's Loaded Image protocol + // + LoadedImage =NULL; + + Status = gBS->OpenProtocol ( + mDriverImageHandleBuffer[Index], + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + FakeNvData->DriSelection[Index] = 0x00; + continue; + } + mDriverImageProtocol[Index] = LoadedImage; + // + // Find its related driver binding protocol + // + DriverBindingHandle = GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer[Index]); + if (DriverBindingHandle == NULL) { + FakeNvData->DriSelection[Index] = 0x00; + continue; + } + + // + // Get the EFI Loaded Image Device Path Protocol + // + LoadedImageDevicePath = NULL; + Status = gBS->HandleProtocol ( + mDriverImageHandleBuffer[Index], + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + if (LoadedImageDevicePath == NULL) { + FakeNvData->DriSelection[Index] = 0x00; + continue; + } + + if (FakeNvData->PciDeviceFilter == 0x01) { + // + // only care the driver which is in a Pci device option rom, + // and the driver's LoadedImage->DeviceHandle must point to a pci device which has efi option rom + // + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol( + LoadedImage->DeviceHandle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID **) &BusSpecificDriverOverride + ); + if (EFI_ERROR (Status) || BusSpecificDriverOverride == NULL) { + FakeNvData->DriSelection[Index] = 0x00; + continue; + } + } else { + FakeNvData->DriSelection[Index] = 0x00; + continue; + } + } + + // + // For driver name, try to get its component name, if fail, get its image name, + // if also fail, give a default name. + // + FreeDriverName = FALSE; + DriverName = GetComponentName (DriverBindingHandle); + if (DriverName == NULL) { + // + // get its image name + // + DriverName = GetImageName (LoadedImage); + } + if (DriverName == NULL) { + // + // give a default name + // + DriverName = HiiGetString (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), NULL); + ASSERT (DriverName != NULL); + FreeDriverName = TRUE; // the DriverName string need to free pool + } + + + // + // Step2 Export the driver name string and create check box item in second page + // + + // + // First create the driver image name + // + NewString = AllocateZeroPool (StrSize (DriverName)); + ASSERT (NewString != NULL); + if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) { + FakeNvData->DriSelection[Index] = 0x00; + } else { + FakeNvData->DriSelection[Index] = 0x01; + mLastSavedDriverImageNum++; + } + StrCat (NewString, DriverName); + NewStringToken = HiiSetString (Private->RegisteredHandle, mDriverImageToken[Index], NewString, NULL); + ASSERT (NewStringToken != 0); + mDriverImageToken[Index] = NewStringToken; + FreePool (NewString); + if (FreeDriverName) { + FreePool (DriverName); + } + + // + // Second create the driver image device path as item help string + // + DriverName = DevicePathToStr (LoadedImageDevicePath); + + NewString = AllocateZeroPool (StrSize (DriverName)); + ASSERT (NewString != NULL); + StrCat (NewString, DriverName); + NewStringHelpToken = HiiSetString (Private->RegisteredHandle, mDriverImageFilePathToken[Index], NewString, NULL); + ASSERT (NewStringHelpToken != 0); + mDriverImageFilePathToken[Index] = NewStringHelpToken; + FreePool (NewString); + FreePool (DriverName); + + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index), + VARSTORE_ID_PLAT_OVER_MNGR, + (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index), + NewStringToken, + NewStringHelpToken, + 0, + 0, + NULL + ); + } + + // + // Update second page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_DRIVER, + StartOpCodeHandle, // Label FORM_ID_DRIVER + EndOpCodeHandle // LABEL_END + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + return EFI_SUCCESS; +} + +/** + Prepare to let user select the priority order of the drivers which are + selected in second page. + + @param Private Pointer to EFI_CALLBACK_INFO. + @param KeyValue The callback key value of device controller item in first page. + @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +UpdatePrioritySelectPage ( + IN EFI_CALLBACK_INFO *Private, + IN UINT16 KeyValue, + IN PLAT_OVER_MNGR_DATA *FakeNvData + ) +{ + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + UINTN SelectedDriverImageNum; + UINT32 DriverImageNO; + UINTN MinNO; + UINTN Index1; + UINTN TempNO[100]; + UINTN OrderNO[100]; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + VOID *OptionsOpCodeHandle; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + + // + // Following code will be run if user select 'order ... priority' item in second page + // Prepare third page. In third page, user will order the drivers priority which are selected in second page + // + mCurrentPage = FORM_ID_ORDER; + + // + // Init OpCode Handle + // + StartOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (StartOpCodeHandle != NULL); + + EndOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (EndOpCodeHandle != NULL); + + // + // Create Hii Extend Label OpCode as the start opcode + // + StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (StartOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartLabel->Number = FORM_ID_ORDER; + + // + // Create Hii Extend Label OpCode as the end opcode + // + EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (EndOpCodeHandle, &gEfiIfrTianoGuid, NULL, sizeof (EFI_IFR_GUID_LABEL)); + EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndLabel->Number = LABEL_END; + + // + // Clear third page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_ORDER, + StartOpCodeHandle, + EndOpCodeHandle + ); + + // + // Check how many drivers have been selected + // + SelectedDriverImageNum = 0; + for (Index = 0; Index < mDriverImageHandleCount; Index++) { + if (FakeNvData->DriSelection[Index] != 0) { + SelectedDriverImageNum ++; + } + } + + mSelectedDriverImageNum = SelectedDriverImageNum; + if (SelectedDriverImageNum == 0) { + return EFI_SUCCESS; + } + + OptionsOpCodeHandle = HiiAllocateOpCodeHandle (); + ASSERT (OptionsOpCodeHandle != NULL); + + // + // Create order list for those selected drivers + // + SelectedDriverImageNum = 0; + for (Index = 0; Index < mDriverImageHandleCount; Index++) { + if (FakeNvData->DriSelection[Index] != 0) { + // + // Use the NO. in driver binding buffer as value, will use it later + // + HiiCreateOneOfOptionOpCode ( + OptionsOpCodeHandle, + mDriverImageToken[Index], + 0, + EFI_IFR_NUMERIC_SIZE_1, + Index + 1 + ); + + // + // Get the EFI Loaded Image Device Path Protocol + // + LoadedImageDevicePath = NULL; + gBS->HandleProtocol ( + mDriverImageHandleBuffer[Index], + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + ASSERT (LoadedImageDevicePath != NULL); + + // + // Check the driver DriverImage's order number in mapping database + // + DriverImageNO = 0; + CheckMapping ( + mControllerDevicePathProtocol[mSelectedCtrIndex], + LoadedImageDevicePath, + &mMappingDataBase, + NULL, + &DriverImageNO + ); + if (DriverImageNO == 0) { + DriverImageNO = (UINT32) mLastSavedDriverImageNum + 1; + mLastSavedDriverImageNum++; + } + TempNO[SelectedDriverImageNum] = DriverImageNO; + OrderNO[SelectedDriverImageNum] = Index + 1; + SelectedDriverImageNum ++; + } + } + + ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum); + // + // NvRamMap Must be clear firstly + // + ZeroMem (FakeNvData->DriOrder, sizeof (FakeNvData->DriOrder)); + + // + // Order the selected drivers according to the info already in mapping database + // the less order number in mapping database the less order number in NvRamMap + // + for (Index=0; Index < SelectedDriverImageNum; Index++) { + // + // Find the minimal order number in TempNO array, its index in TempNO is same as IfrOptionList array + // + MinNO = 0; + for (Index1=0; Index1 < SelectedDriverImageNum; Index1++) { + if (TempNO[Index1] < TempNO[MinNO]) { + MinNO = Index1; + } + } + // + // the IfrOptionList[MinNO].Value = the driver NO. in driver binding buffer + // + FakeNvData->DriOrder[Index] = (UINT8) OrderNO[MinNO]; + TempNO[MinNO] = MAX_CHOICE_NUM + 1; + } + + // + // Create Order List OpCode + // + HiiCreateOrderedListOpCode ( + StartOpCodeHandle, + (UINT16) DRIVER_ORDER_QUESTION_ID, + VARSTORE_ID_PLAT_OVER_MNGR, + (UINT16) DRIVER_ORDER_VAR_OFFSET, + mControllerToken[mSelectedCtrIndex], + mControllerToken[mSelectedCtrIndex], + EFI_IFR_FLAG_RESET_REQUIRED, + 0, + EFI_IFR_NUMERIC_SIZE_1, + (UINT8) MAX_CHOICE_NUM, + OptionsOpCodeHandle, + NULL + ); + + // + // Update third page form + // + HiiUpdateForm ( + Private->RegisteredHandle, + &mPlatformOverridesManagerGuid, + FORM_ID_ORDER, + StartOpCodeHandle, // Label FORM_ID_ORDER + EndOpCodeHandle // LABEL_END + ); + + HiiFreeOpCodeHandle (StartOpCodeHandle); + HiiFreeOpCodeHandle (EndOpCodeHandle); + HiiFreeOpCodeHandle (OptionsOpCodeHandle); + + return EFI_SUCCESS; +} + +/** + Save the save the mapping database to NV variable. + + @param Private Pointer to EFI_CALLBACK_INFO. + @param KeyValue The callback key value of device controller item in first page. + @param FakeNvData Pointer to PLAT_OVER_MNGR_DATA. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +CommintChanges ( + IN EFI_CALLBACK_INFO *Private, + IN UINT16 KeyValue, + IN PLAT_OVER_MNGR_DATA *FakeNvData + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN SelectedDriverImageNum; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + // + // Following code will be run if user select 'commint changes' in third page + // user enter 'Commit Changes' to save the mapping database + // + DeleteDriverImage (mControllerDevicePathProtocol[mSelectedCtrIndex], NULL, &mMappingDataBase); + for (SelectedDriverImageNum = 0; SelectedDriverImageNum < mSelectedDriverImageNum; SelectedDriverImageNum++) { + // + // DriOrder[SelectedDriverImageNum] = the driver NO. in driver binding buffer + // + Index = FakeNvData->DriOrder[SelectedDriverImageNum] - 1; + + // + // Get the EFI Loaded Image Device Path Protocol + // + LoadedImageDevicePath = NULL; + Status = gBS->HandleProtocol ( + mDriverImageHandleBuffer[Index], + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + ASSERT (LoadedImageDevicePath != NULL); + + InsertDriverImage ( + mControllerDevicePathProtocol[mSelectedCtrIndex], + LoadedImageDevicePath, + &mMappingDataBase, + (UINT32)SelectedDriverImageNum + 1 + ); + } + Status = SaveOverridesMapping (&mMappingDataBase); + + return Status; +} + +/** + This function allows a caller to extract the current configuration for one + or more named elements from the target driver. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Request A null-terminated Unicode string in format. + @param Progress On return, points to a character in the Request string. + Points to the string's null terminator if request was successful. + Points to the most recent '&' before the first failing name/value + pair (or the beginning of the string if the failure is in the + first name/value pair) if the request was not successful. + @param Results A null-terminated Unicode string in format which + has all values filled in for the names in the Request string. + String to be allocated by the called function. + + @retval EFI_SUCCESS The Results is filled with the requested values. + @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. + @retval EFI_INVALID_PARAMETER Request is NULL, illegal syntax, or unknown name. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +PlatOverMngrExtractConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Request, + OUT EFI_STRING *Progress, + OUT EFI_STRING *Results + ) +{ + EFI_STATUS Status; + EFI_CALLBACK_INFO *Private; + EFI_HII_CONFIG_ROUTING_PROTOCOL *HiiConfigRouting; + + if (Request == NULL) { + return EFI_NOT_FOUND; + } + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + HiiConfigRouting = Private->HiiConfigRouting; + + // + // Convert buffer data to by helper function BlockToConfig() + // + Status = HiiConfigRouting->BlockToConfig ( + HiiConfigRouting, + Request, + (UINT8 *) &Private->FakeNvData, + sizeof (PLAT_OVER_MNGR_DATA), + Results, + Progress + ); + return Status; +} + +/** + This function processes the results of changes in configuration. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Configuration A null-terminated Unicode string in format. + @param Progress A pointer to a string filled in with the offset of the most + recent '&' before the first failing name/value pair (or the + beginning of the string if the failure is in the first + name/value pair) or the terminating NULL if all was successful. + + @retval EFI_SUCCESS The Results is processed successfully. + @retval EFI_INVALID_PARAMETER Configuration is NULL. + @retval EFI_NOT_FOUND Routing data doesn't match any storage in this driver. + +**/ +EFI_STATUS +EFIAPI +PlatOverMngrRouteConfig ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN CONST EFI_STRING Configuration, + OUT EFI_STRING *Progress + ) +{ + EFI_CALLBACK_INFO *Private; + UINT16 KeyValue; + PLAT_OVER_MNGR_DATA *FakeNvData; + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA)); + if (FakeNvData == NULL) { + return EFI_NOT_FOUND; + } + + if (mCurrentPage == FORM_ID_DRIVER) { + KeyValue = KEY_VALUE_DRIVER_GOTO_ORDER; + UpdatePrioritySelectPage (Private, KeyValue, FakeNvData); + KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT; + CommintChanges (Private, KeyValue, FakeNvData); + // + // Since UpdatePrioritySelectPage will change mCurrentPage, + // should ensure the mCurrentPage still indicate the second page here + // + mCurrentPage = FORM_ID_DRIVER; + } + + if (mCurrentPage == FORM_ID_ORDER) { + KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT; + CommintChanges (Private, KeyValue, FakeNvData); + } + + if (FakeNvData != NULL) { + FreePool (FakeNvData); + } + + return EFI_SUCCESS; +} + +/** + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + + @param This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. + @param Action A null-terminated Unicode string in format. + @param KeyValue A unique Goto OpCode callback value which record user's selection. + 0x100 <= KeyValue <0x500 : user select a controller item in the first page; + KeyValue == 0x1234 : user select 'Refresh' in first page, or user select 'Go to Previous Menu' in second page + KeyValue == 0x1235 : user select 'Pci device filter' in first page + KeyValue == 0x1500 : user select 'order ... priority' item in second page + KeyValue == 0x1800 : user select 'commint changes' in third page + KeyValue == 0x2000 : user select 'Go to Previous Menu' in third page + @param Type The type of value for the question. + @param Value A pointer to the data being sent to the original exporting driver. + @param ActionRequest On return, points to the action requested by the callback function. + + @retval EFI_SUCCESS Always returned. + +**/ +EFI_STATUS +EFIAPI +PlatOverMngrCallback ( + IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, + IN EFI_BROWSER_ACTION Action, + IN EFI_QUESTION_ID KeyValue, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE *Value, + OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest + ) +{ + EFI_CALLBACK_INFO *Private; + EFI_STATUS Status; + EFI_STRING_ID NewStringToken; + EFI_INPUT_KEY Key; + PLAT_OVER_MNGR_DATA *FakeNvData; + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + FakeNvData = (PLAT_OVER_MNGR_DATA *) HiiGetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA)); + if (FakeNvData == NULL) { + return EFI_NOT_FOUND; + } + + if (KeyValue == KEY_VALUE_DEVICE_REFRESH || + KeyValue == KEY_VALUE_DEVICE_FILTER || + KeyValue == KEY_VALUE_DRIVER_GOTO_PREVIOUS + ) { + UpdateDeviceSelectPage (Private, KeyValue, FakeNvData); + // + // Update page title string + // + NewStringToken = STRING_TOKEN (STR_TITLE); + if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path", NULL) == 0) { + ASSERT (FALSE); + } + } + + if (((KeyValue >= KEY_VALUE_DEVICE_OFFSET) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) { + if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) { + KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + KEY_VALUE_DEVICE_OFFSET); + } + UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData); + // + // Update page title string + // + NewStringToken = STRING_TOKEN (STR_TITLE); + if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller", NULL) == 0) { + ASSERT (FALSE); + } + } + + if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) { + UpdatePrioritySelectPage (Private, KeyValue, FakeNvData); + // + // Update page title string + // + NewStringToken = STRING_TOKEN (STR_TITLE); + if (HiiSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them", NULL) == 0) { + ASSERT (FALSE); + } + } + + if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) { + Status = CommintChanges (Private, KeyValue, FakeNvData); + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; + if (EFI_ERROR (Status)) { + CreatePopUp (EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"Single Override Info too large, Saving Error!", NULL); + return EFI_DEVICE_ERROR; + } + } + + if (KeyValue == KEY_VALUE_DEVICE_CLEAR) { + // + // Deletes all environment variable(s) that contain the override mappings info + // + FreeMappingDatabase (&mMappingDataBase); + Status = SaveOverridesMapping (&mMappingDataBase); + UpdateDeviceSelectPage (Private, KeyValue, FakeNvData); + } + // + // Pass changed uncommitted data back to Form Browser + // + HiiSetBrowserData (&mPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL); + + // + // Update local configuration buffer. + // + CopyMem (&Private->FakeNvData, FakeNvData, sizeof (PLAT_OVER_MNGR_DATA)); + if (FakeNvData != NULL) { + FreePool (FakeNvData); + } + + return EFI_SUCCESS; +} + +/** + Retrieves the image handle of the platform override driver for a controller in the system. + + @param This A pointer to the + EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a + driver override exists. + @param DriverImageHandle On input, a pointer to the previous driver image + handle returned by GetDriver(). On output, a + pointer to the next driver image handle. Passing + in a NULL, will return the first driver image + handle for ControllerHandle. + + @retval EFI_SUCCESS The driver override for ControllerHandle was + returned in DriverImageHandle. + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not + found. + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a + valid handle. DriverImageHandle is not a handle + that was returned on a previous call to + GetDriver(). + +**/ +EFI_STATUS +EFIAPI +GetDriver ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE *DriverImageHandle + ) +{ + EFI_STATUS Status; + + // + // Check that ControllerHandle is a valid handle + // + if (ControllerHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Read the environment variable(s) that contain the override mappings from Controller Device Path to + // a set of Driver Device Paths, and initialize in memory database of the overrides that map Controller + // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed + // once and finished in first call. + // + if (!mEnvironmentVariableRead) { + mEnvironmentVariableRead = TRUE; + + Status = InitOverridesMapping (&mMappingDataBase); + if (EFI_ERROR (Status)){ + DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status)); + InitializeListHead (&mMappingDataBase); + return EFI_NOT_FOUND; + } + } + + // + // if the environment variable does not exist, just return not found + // + if (IsListEmpty (&mMappingDataBase)) { + return EFI_NOT_FOUND; + } + + return GetDriverFromMapping ( + ControllerHandle, + DriverImageHandle, + &mMappingDataBase, + mCallerImageHandle + ); +} + +/** + Retrieves the device path of the platform override driver for a controller in the system. + This driver doesn't support this API. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a driver override + exists. + @param DriverImagePath On input, a pointer to the previous driver device path returned by + GetDriverPath(). On output, a pointer to the next driver + device path. Passing in a pointer to NULL, will return the first + driver device path for ControllerHandle. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +GetDriverPath ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Used to associate a driver image handle with a device path that was returned on a prior call to the + GetDriverPath() service. This driver image handle will then be available through the + GetDriver() service. This driver doesn't support this API. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller. + @param DriverImagePath A pointer to the driver device path that was returned in a prior + call to GetDriverPath(). + @param DriverImageHandle The driver image handle that was returned by LoadImage() + when the driver specified by DriverImagePath was loaded + into memory. + + @retval EFI_UNSUPPORTED +**/ +EFI_STATUS +EFIAPI +DriverLoaded ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath, + IN EFI_HANDLE DriverImageHandle + ) +{ + return EFI_UNSUPPORTED; +} + +/** + The driver Entry Point. The funciton will export a disk device class formset and + its callback function to hii database. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +PlatDriOverrideDxeInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; + VOID *Instance; + + // + // There should only be one Form Configuration protocol + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowser2ProtocolGuid, + NULL, + (VOID **) &FormBrowser2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // According to UEFI spec, there can be at most a single instance + // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL. + // So here we check the existence. + // + Status = gBS->LocateProtocol ( + &gEfiPlatformDriverOverrideProtocolGuid, + NULL, + &Instance + ); + // + // If there was no error, assume there is an installation and return error + // + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + + mCallerImageHandle = ImageHandle; + mCallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO)); + if (mCallbackInfo == NULL) { + return EFI_BAD_BUFFER_SIZE; + } + + mCallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE; + mCallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig; + mCallbackInfo->ConfigAccess.RouteConfig = PlatOverMngrRouteConfig; + mCallbackInfo->ConfigAccess.Callback = PlatOverMngrCallback; + mCallbackInfo->PlatformDriverOverride.GetDriver = GetDriver; + mCallbackInfo->PlatformDriverOverride.GetDriverPath = GetDriverPath; + mCallbackInfo->PlatformDriverOverride.DriverLoaded = DriverLoaded; + // + // Install Device Path Protocol and Config Access protocol to driver handle + // Install Platform Driver Override Protocol to driver handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + &gEfiPlatformDriverOverrideProtocolGuid, + &mCallbackInfo->PlatformDriverOverride, + NULL + ); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Publish our HII data + // + mCallbackInfo->RegisteredHandle = HiiAddPackages ( + &mPlatformOverridesManagerGuid, + mCallbackInfo->DriverHandle, + VfrBin, + PlatDriOverrideDxeStrings, + NULL + ); + if (mCallbackInfo->RegisteredHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + // + // Locate ConfigRouting protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiConfigRoutingProtocolGuid, + NULL, + (VOID **) &mCallbackInfo->HiiConfigRouting + ); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Clear all the globle variable + // + mDriverImageHandleCount = 0; + mCurrentPage = 0; + ZeroMem (mDriverImageToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); + ZeroMem (mDriverImageFilePathToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); + ZeroMem (mControllerToken, MAX_CHOICE_NUM * sizeof (EFI_STRING_ID)); + ZeroMem (mDriverImageProtocol, MAX_CHOICE_NUM * sizeof (EFI_LOADED_IMAGE_PROTOCOL *)); + + return EFI_SUCCESS; + +Finish: + if (mCallbackInfo->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + &gEfiPlatformDriverOverrideProtocolGuid, + &mCallbackInfo->PlatformDriverOverride, + NULL + ); + } + + if (mCallbackInfo->RegisteredHandle != NULL) { + HiiRemovePackages (mCallbackInfo->RegisteredHandle); + } + + if (mCallbackInfo != NULL) { + FreePool (mCallbackInfo); + } + + return Status; +} + +/** + Unload its installed protocol. + + @param[in] ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. +**/ +EFI_STATUS +EFIAPI +PlatDriOverrideDxeUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + if (mCallbackInfo->DriverHandle != NULL) { + gBS->UninstallMultipleProtocolInterfaces ( + mCallbackInfo->DriverHandle, + &gEfiDevicePathProtocolGuid, + &mHiiVendorDevicePath, + &gEfiHiiConfigAccessProtocolGuid, + &mCallbackInfo->ConfigAccess, + &gEfiPlatformDriverOverrideProtocolGuid, + &mCallbackInfo->PlatformDriverOverride, + NULL + ); + } + + if (mCallbackInfo->RegisteredHandle != NULL) { + HiiRemovePackages (mCallbackInfo->RegisteredHandle); + } + + if (mCallbackInfo != NULL) { + FreePool (mCallbackInfo); + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c new file mode 100644 index 0000000000..48beba06e8 --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatDriOverrideLib.c @@ -0,0 +1,1898 @@ +/** @file + Implementation of the shared functions to do the platform driver vverride mapping. + + Copyright (c) 2007 - 2009, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include "InternalPlatDriOverrideDxe.h" + +#define PLATFORM_OVERRIDE_ITEM_SIGNATURE SIGNATURE_32('p','d','o','i') + typedef struct _PLATFORM_OVERRIDE_ITEM { + UINTN Signature; + LIST_ENTRY Link; + UINT32 DriverInfoNum; + EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; + /// + /// List of DRIVER_IMAGE_INFO + /// + LIST_ENTRY DriverInfoList; + EFI_HANDLE LastReturnedImageHandle; +} PLATFORM_OVERRIDE_ITEM; + +#define DRIVER_IMAGE_INFO_SIGNATURE SIGNATURE_32('p','d','i','i') +typedef struct _DRIVER_IMAGE_INFO { + UINTN Signature; + LIST_ENTRY Link; + EFI_HANDLE ImageHandle; + EFI_DEVICE_PATH_PROTOCOL *DriverImagePath; + BOOLEAN UnLoadable; + BOOLEAN UnStartable; +} DRIVER_IMAGE_INFO; + +#define DEVICE_PATH_STACK_ITEM_SIGNATURE SIGNATURE_32('d','p','s','i') +typedef struct _DEVICE_PATH_STACK_ITEM{ + UINTN Signature; + LIST_ENTRY Link; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} DEVICE_PATH_STACK_ITEM; + + +LIST_ENTRY mDevicePathStack = INITIALIZE_LIST_HEAD_VARIABLE (mDevicePathStack); + +/** + Push a controller device path into a globle device path list. + + @param DevicePath The controller device path to push into stack + + @retval EFI_SUCCESS Device path successfully pushed into the stack. + +**/ +EFI_STATUS +EFIAPI +PushDevPathStack ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + DEVICE_PATH_STACK_ITEM *DevicePathStackItem; + + DevicePathStackItem = AllocateZeroPool (sizeof (DEVICE_PATH_STACK_ITEM)); + ASSERT (DevicePathStackItem != NULL); + DevicePathStackItem->Signature = DEVICE_PATH_STACK_ITEM_SIGNATURE; + DevicePathStackItem->DevicePath = DuplicateDevicePath (DevicePath); + InsertTailList (&mDevicePathStack, &DevicePathStackItem->Link); + return EFI_SUCCESS; +} + + +/** + Pop a controller device path from a globle device path list + + @param DevicePath The controller device path popped from stack + + @retval EFI_SUCCESS Controller device path successfully popped. + @retval EFI_NOT_FOUND Stack is empty. + +**/ +EFI_STATUS +EFIAPI +PopDevPathStack ( + OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +{ + DEVICE_PATH_STACK_ITEM *DevicePathStackItem; + LIST_ENTRY *ItemListIndex; + + ItemListIndex = mDevicePathStack.BackLink; + // + // Check if the stack is empty + // + if (ItemListIndex != &mDevicePathStack){ + DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE); + if (DevicePath != NULL) { + *DevicePath = DuplicateDevicePath (DevicePathStackItem->DevicePath); + } + FreePool (DevicePathStackItem->DevicePath); + RemoveEntryList (&DevicePathStackItem->Link); + FreePool (DevicePathStackItem); + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + + +/** + Check whether a controller device path is in a globle device path list + + @param DevicePath The controller device path to check + + @retval TRUE DevicePath exists in the stack. + @retval FALSE DevicePath does not exist in the stack. + +**/ +BOOLEAN +EFIAPI +CheckExistInStack ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + DEVICE_PATH_STACK_ITEM *DevicePathStackItem; + LIST_ENTRY *ItemListIndex; + UINTN DevicePathSize; + + ItemListIndex = mDevicePathStack.BackLink; + while (ItemListIndex != &mDevicePathStack){ + DevicePathStackItem = CR(ItemListIndex, DEVICE_PATH_STACK_ITEM, Link, DEVICE_PATH_STACK_ITEM_SIGNATURE); + DevicePathSize = GetDevicePathSize (DevicePath); + if (DevicePathSize == GetDevicePathSize (DevicePathStackItem->DevicePath)) { + if (CompareMem (DevicePath, DevicePathStackItem->DevicePath, DevicePathSize) == 0) { + return TRUE; + } + } + ItemListIndex = ItemListIndex->BackLink; + } + + return FALSE; +} + +/** + Update the FV file device path if it is not valid. + + According to a file GUID, check a Fv file device path is valid. If it is invalid, + try to return the valid device path. + FV address maybe changes for memory layout adjust from time to time, use this funciton + could promise the Fv file device path is right. + + @param DevicePath On input, the FV file device path to check + On output, the updated valid FV file device path + @param FileGuid The FV file GUID + @param CallerImageHandle Image handle of the caller + + @retval EFI_INVALID_PARAMETER the input DevicePath or FileGuid is invalid + parameter + @retval EFI_UNSUPPORTED the input DevicePath does not contain FV file + GUID at all + @retval EFI_ALREADY_STARTED the input DevicePath has pointed to FV file, it + is valid + @retval EFI_SUCCESS Successfully updated the invalid DevicePath, + and return the updated device path in DevicePath + +**/ +EFI_STATUS +EFIAPI +UpdateFvFileDevicePath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + IN EFI_GUID *FileGuid, + IN EFI_HANDLE CallerImageHandle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *LastDeviceNode; + EFI_STATUS Status; + EFI_GUID *GuidPoint; + UINTN Index; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + BOOLEAN FindFvFile; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FvFileNode; + EFI_HANDLE FoundFvHandle; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + BOOLEAN HasFvNode; + + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (*DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the device path points to the default the input FV file + // + TempDevicePath = *DevicePath; + LastDeviceNode = TempDevicePath; + while (!IsDevicePathEnd (TempDevicePath)) { + LastDeviceNode = TempDevicePath; + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + GuidPoint = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) LastDeviceNode); + if (GuidPoint == NULL) { + // + // If this option does not point to a FV file, just return EFI_UNSUPPORTED. + // + return EFI_UNSUPPORTED; + } + + if (FileGuid != NULL) { + if (!CompareGuid (GuidPoint, FileGuid)) { + // + // If the FV file is not the input file GUID, just return EFI_UNSUPPORTED + // + return EFI_UNSUPPORTED; + } + } else { + FileGuid = GuidPoint; + } + + // + // Check to see if the device path contains memory map node + // + TempDevicePath = *DevicePath; + HasFvNode = FALSE; + while (!IsDevicePathEnd (TempDevicePath)) { + // + // Use old Device Path + // + if (DevicePathType (TempDevicePath) == HARDWARE_DEVICE_PATH && + DevicePathSubType (TempDevicePath) == HW_MEMMAP_DP) { + HasFvNode = TRUE; + break; + } + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + if (!HasFvNode) { + return EFI_UNSUPPORTED; + } + + // + // Check whether the input Fv file device path is valid + // + TempDevicePath = *DevicePath; + FoundFvHandle = NULL; + Status = gBS->LocateDevicePath ( + &gEfiFirmwareVolume2ProtocolGuid, + &TempDevicePath, + &FoundFvHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + FoundFvHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + // + // Set FV ReadFile Buffer as NULL, only need to check whether input Fv file exist there + // + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + return EFI_ALREADY_STARTED; + } + } + } + + // + // Look for the input wanted FV file in current FV + // First, try to look for in Caller own FV. Caller and input wanted FV file usually are in the same FV + // + FindFvFile = FALSE; + FoundFvHandle = NULL; + Status = gBS->HandleProtocol ( + CallerImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImage + ); + if (!EFI_ERROR (Status)) { + Status = gBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + if (!EFI_ERROR (Status)) { + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + FindFvFile = TRUE; + FoundFvHandle = LoadedImage->DeviceHandle; + } + } + } + // + // Second, if fail to find, try to enumerate all FV + // + if (!FindFvFile) { + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + for (Index = 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **) &Fv + ); + + Status = Fv->ReadFile ( + Fv, + FileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if input Fv file not in the FV + // + continue; + } + FindFvFile = TRUE; + FoundFvHandle = FvHandleBuffer[Index]; + break; + } + } + + if (FindFvFile) { + // + // Build the shell device path + // + NewDevicePath = DevicePathFromHandle (FoundFvHandle); + EfiInitializeFwVolDevicepathNode (&FvFileNode, FileGuid); + NewDevicePath = AppendDevicePathNode (NewDevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &FvFileNode); + *DevicePath = NewDevicePath; + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +/** + Gets the data and size of a variable. + + Read the EFI variable (VendorGuid/Name) and return a dynamically allocated + buffer, and the size of the buffer. If failure return NULL. + + @param Name String part of EFI variable name + @param VendorGuid GUID part of EFI variable name + @param VariableSize Returns the size of the EFI variable that was + read + + @return Dynamically allocated memory that contains a copy of the EFI variable. + Caller is responsible freeing the buffer. + @retval NULL Variable was not read + +**/ +VOID * +EFIAPI +GetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; + + Buffer = NULL; + + // + // Pass in a zero size buffer to find the required buffer size. + // + BufferSize = 0; + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (EFI_ERROR (Status)) { + BufferSize = 0; + } + } + + *VariableSize = BufferSize; + return Buffer; +} + +/** + Connect to the handle to a device on the device path. + + This function will create all handles associate with every device + path node. If the handle associate with one device path node can not + be created success, then still give one chance to do the dispatch, + which load the missing drivers if possible. + + @param DevicePathToConnect The device path which will be connected, it can + be a multi-instance device path + + @retval EFI_SUCCESS All handles associate with every device path + node have been created + @retval EFI_OUT_OF_RESOURCES There is no resource to create new handles + @retval EFI_NOT_FOUND Create the handle associate with one device + path node failed + +**/ +EFI_STATUS +EFIAPI +ConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_HANDLE Handle; + EFI_HANDLE PreviousHandle; + UINTN Size; + + if (DevicePathToConnect == NULL) { + return EFI_SUCCESS; + } + + DevicePath = DuplicateDevicePath (DevicePathToConnect); + CopyOfDevicePath = DevicePath; + if (DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + do { + // + // The outer loop handles multi instance device paths. + // Only console variables contain multiple instance device paths. + // + // After this call DevicePath points to the next Instance + // + Instance = GetNextDevicePathInstance (&DevicePath, &Size); + ASSERT (Instance != NULL); + + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + + // + // Start the real work of connect with RemainingDevicePath + // + PreviousHandle = NULL; + do { + // + // Find the handle that best matches the Device Path. If it is only a + // partial match the remaining part of the device path is returned in + // RemainingDevicePath. + // + RemainingDevicePath = Instance; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); + + if (!EFI_ERROR (Status)) { + if (Handle == PreviousHandle) { + // + // If no forward progress is made try invoking the Dispatcher. + // A new FV may have been added to the system an new drivers + // may now be found. + // Status == EFI_SUCCESS means a driver was dispatched + // Status == EFI_NOT_FOUND means no new drivers were dispatched + // + Status = gDS->Dispatch (); + } + + if (!EFI_ERROR (Status)) { + PreviousHandle = Handle; + // + // Connect all drivers that apply to Handle and RemainingDevicePath, + // the Recursive flag is FALSE so only one level will be expanded. + // + // Do not check the connect status here, if the connect controller fail, + // then still give the chance to do dispatch, because partial + // RemainingDevicepath may be in the new FV + // + // 1. If the connect fails, RemainingDevicepath and handle will not + // change, so next time will do the dispatch, then dispatch's status + // will take effect + // 2. If the connect succeeds, the RemainingDevicepath and handle will + // change, then avoid the dispatch, we have chance to continue the + // next connection + // + gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); + } + } + // + // Loop until RemainingDevicePath is an empty device path + // + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); + + } while (DevicePath != NULL); + + if (CopyOfDevicePath != NULL) { + FreePool (CopyOfDevicePath); + } + // + // All handle with DevicePath exists in the handle database + // + return Status; +} + +/** + Free all the mapping database memory resource and initialize the mapping list entry. + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_SUCCESS Mapping database successfully freed + @retval EFI_INVALID_PARAMETER MappingDataBase is NULL + +**/ +EFI_STATUS +EFIAPI +FreeMappingDatabase ( + IN OUT LIST_ENTRY *MappingDataBase + ) +{ + LIST_ENTRY *OverrideItemListIndex; + LIST_ENTRY *ImageInfoListIndex; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + DRIVER_IMAGE_INFO *DriverImageInfo; + + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + // + // Free PLATFORM_OVERRIDE_ITEM.ControllerDevicePath[] + // + if (OverrideItem->ControllerDevicePath != NULL){ + FreePool (OverrideItem->ControllerDevicePath); + } + + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + // + // Free DRIVER_IMAGE_INFO.DriverImagePath[] + // + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + if (DriverImageInfo->DriverImagePath != NULL) { + FreePool(DriverImageInfo->DriverImagePath); + } + // + // Free DRIVER_IMAGE_INFO itself + // + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + RemoveEntryList (&DriverImageInfo->Link); + FreePool (DriverImageInfo); + } + // + // Free PLATFORM_OVERRIDE_ITEM itself + // + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + RemoveEntryList (&OverrideItem->Link); + FreePool (OverrideItem); + } + + InitializeListHead (MappingDataBase); + return EFI_SUCCESS; +} + + +/** + Create the mapping database according to variable. + + Read the environment variable(s) that contain the override mappings from Controller Device Path to + a set of Driver Device Paths, and create the mapping database in memory with those variable info. + VariableLayout{ + // + // NotEnd indicate whether the variable is the last one, and has no subsequent variable need to load. + // Each variable has MaximumVariableSize limitation, so we maybe need multiple variables to store + // large mapping infos. + // The variable(s) name rule is PlatDriOver, PlatDriOver1, PlatDriOver2, .... + // + UINT32 NotEnd; //Zero is the last one. + // + // The entry which contains the mapping that Controller Device Path to a set of Driver Device Paths + // There are often multi mapping entries in a variable. + // + UINT32 SIGNATURE; //SIGNATURE_32('p','d','o','i') + UINT32 DriverNum; + EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + ...... + UINT32 NotEnd; //Zero is the last one. + UINT32 SIGNATURE; + UINT32 DriverNum; + EFI_DEVICE_PATH_PROTOCOL ControllerDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + EFI_DEVICE_PATH_PROTOCOL DriverDevicePath[]; + ...... + } + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_SUCCESS Create the mapping database in memory successfully + @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null + @retval EFI_NOT_FOUND Cannot find the 'PlatDriOver' NV variable + @retval EFI_VOLUME_CORRUPTED The found NV variable is corrupted + +**/ +EFI_STATUS +EFIAPI +InitOverridesMapping ( + OUT LIST_ENTRY *MappingDataBase + ) +{ + UINTN BufferSize; + VOID *VariableBuffer; + UINT8 *VariableIndex; + UINTN VariableNum; + CHAR16 OverrideVariableName[40]; + UINT32 NotEnd; + UINT32 DriverNumber; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + DRIVER_IMAGE_INFO *DriverImageInfo; + BOOLEAN Corrupted; + UINT32 Signature; + EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath; + UINTN Index; + + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check the environment variable(s) that contain the override mappings . + // + VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize); + ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); + if (VariableBuffer == NULL) { + return EFI_NOT_FOUND; + } + + // + // Traverse all variables. + // + VariableNum = 1; + Corrupted = FALSE; + do { + VariableIndex = VariableBuffer; + // + // End flag + // + NotEnd = *(UINT32*) VariableIndex; + // + // Traverse the entries containing the mapping that Controller Device Path + // to a set of Driver Device Paths within this variable. + // + VariableIndex = VariableIndex + sizeof (UINT32); + while (VariableIndex < ((UINT8 *)VariableBuffer + BufferSize)) { + // + // Check signature of this entry + // + Signature = *(UINT32 *) VariableIndex; + if (Signature != PLATFORM_OVERRIDE_ITEM_SIGNATURE) { + Corrupted = TRUE; + break; + } + // + // Create PLATFORM_OVERRIDE_ITEM for this mapping + // + OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM)); + ASSERT (OverrideItem != NULL); + OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE; + InitializeListHead (&OverrideItem->DriverInfoList); + VariableIndex = VariableIndex + sizeof (UINT32); + // + // Get DriverNum + // + DriverNumber = *(UINT32*) VariableIndex; + OverrideItem->DriverInfoNum = DriverNumber; + VariableIndex = VariableIndex + sizeof (UINT32); + // + // Get ControllerDevicePath[] + // + ControllerDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex; + OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath); + VariableIndex = VariableIndex + GetDevicePathSize (ControllerDevicePath); + // + // Align the VariableIndex since the controller device path may not be aligned, refer to the SaveOverridesMapping() + // + VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); + + // + // Get all DriverImageDevicePath[] + // + for (Index = 0; Index < DriverNumber; Index++) { + // + // Create DRIVER_IMAGE_INFO for this DriverDevicePath[] + // + DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO)); + ASSERT (DriverImageInfo != NULL); + DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE; + + DriverDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) VariableIndex; + DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverDevicePath); + VariableIndex = VariableIndex + GetDevicePathSize (DriverDevicePath); + // + // Align the VariableIndex since the driver image device path may not be aligned, refer to the SaveOverridesMapping() + // + VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); + + InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link); + } + InsertTailList (MappingDataBase, &OverrideItem->Link); + } + + FreePool (VariableBuffer); + if (Corrupted) { + FreeMappingDatabase (MappingDataBase); + return EFI_VOLUME_CORRUPTED; + } + + // + // If there are additional variables (PlatDriOver1, PlatDriOver2, PlatDriOver3.....), get them. + // NotEnd indicates whether current variable is the end variable. + // + if (NotEnd != 0) { + UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum++); + VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize); + ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); + if (VariableBuffer == NULL) { + FreeMappingDatabase (MappingDataBase); + return EFI_VOLUME_CORRUPTED; + } + } + + } while (NotEnd != 0); + + return EFI_SUCCESS; +} + + +/** + Calculate the needed size in NV variable for recording a specific PLATFORM_OVERRIDE_ITEM info. + + @param OverrideItemListIndex Pointer to the list of a specific PLATFORM_OVERRIDE_ITEM + + @return The needed size number + +**/ +UINTN +EFIAPI +GetOneItemNeededSize ( + IN LIST_ENTRY *OverrideItemListIndex + ) +{ + UINTN NeededSize; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + LIST_ENTRY *ImageInfoListIndex; + DRIVER_IMAGE_INFO *DriverImageInfo; + UINTN DevicePathSize; + + NeededSize = 0; + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + NeededSize += sizeof (UINT32); //UINT32 SIGNATURE; + NeededSize += sizeof (UINT32); //UINT32 DriverNum; + DevicePathSize = GetDevicePathSize (OverrideItem->ControllerDevicePath); + NeededSize += DevicePathSize; // ControllerDevicePath + // + // Align the controller device path + // + NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1)); + // + // Traverse the Driver Info List of this Override Item + // + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath); + NeededSize += DevicePathSize; //DriverDevicePath + // + // Align the driver image device path + // + NeededSize += ((sizeof(UINT32) - DevicePathSize) & (sizeof(UINT32) - 1)); + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + + return NeededSize; +} + +/** + Deletes all environment variable(s) that contain the override mappings from Controller Device Path to + a set of Driver Device Paths. + + @retval EFI_SUCCESS Delete all variable(s) successfully. + +**/ +EFI_STATUS +EFIAPI +DeleteOverridesVariables ( + VOID + ) +{ + EFI_STATUS Status; + VOID *VariableBuffer; + UINTN VariableNum; + UINTN BufferSize; + UINTN Index; + CHAR16 OverrideVariableName[40]; + + // + // Get environment variable(s) number + // + VariableNum = 0; + VariableBuffer = GetVariableAndSize (L"PlatDriOver", &gEfiCallerIdGuid, &BufferSize); + VariableNum++; + if (VariableBuffer == NULL) { + return EFI_NOT_FOUND; + } + // + // Check NotEnd to get all PlatDriOverX variable(s) + // + while ((*(UINT32*)VariableBuffer) != 0) { + UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", VariableNum); + VariableBuffer = GetVariableAndSize (OverrideVariableName, &gEfiCallerIdGuid, &BufferSize); + VariableNum++; + ASSERT (VariableBuffer != NULL); + } + + // + // Delete PlatDriOver and all additional variables, if exist. + // + Status = gRT->SetVariable ( + L"PlatDriOver", + &gEfiCallerIdGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + ASSERT (!EFI_ERROR (Status)); + for (Index = 1; Index < VariableNum; Index++) { + UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", Index); + Status = gRT->SetVariable ( + OverrideVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + NULL + ); + ASSERT (!EFI_ERROR (Status)); + } + return EFI_SUCCESS; +} + + +/** + Save the memory mapping database into NV environment variable(s). + + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_SUCCESS Save memory mapping database successfully + @retval EFI_INVALID_PARAMETER MappingDataBase pointer is null + +**/ +EFI_STATUS +EFIAPI +SaveOverridesMapping ( + IN LIST_ENTRY *MappingDataBase + ) +{ + EFI_STATUS Status; + VOID *VariableBuffer; + UINT8 *VariableIndex; + UINTN NumIndex; + CHAR16 OverrideVariableName[40]; + UINT32 NotEnd; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + DRIVER_IMAGE_INFO *DriverImageInfo; + LIST_ENTRY *OverrideItemListIndex; + LIST_ENTRY *ItemIndex; + LIST_ENTRY *ImageInfoListIndex; + UINTN VariableNeededSize; + UINT64 MaximumVariableStorageSize; + UINT64 RemainingVariableStorageSize; + UINT64 MaximumVariableSize; + UINTN OneItemNeededSize; + + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (IsListEmpty (MappingDataBase)) { + Status = DeleteOverridesVariables (); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; + } + + // + // Get the the maximum size of an individual EFI variable in current system + // + gRT->QueryVariableInfo ( + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + &MaximumVariableStorageSize, + &RemainingVariableStorageSize, + &MaximumVariableSize + ); + + NumIndex = 0; + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + // + // Try to find the most proper variable size which <= MaximumVariableSize, + // but can contain mapping info as much as possible + // + VariableNeededSize = sizeof (UINT32); // NotEnd; + ItemIndex = OverrideItemListIndex; + NotEnd = FALSE; + // + // Traverse all PLATFORM_OVERRIDE_ITEMs and get the total size. + // + while (!IsNull (MappingDataBase, ItemIndex)) { + OneItemNeededSize = GetOneItemNeededSize (ItemIndex); + // + // If the total size exceeds the MaximumVariableSize, then we must use + // multiple variables. + // + if ((VariableNeededSize + + OneItemNeededSize + + sizeof (VARIABLE_HEADER) + + StrSize (L"PlatDriOver ") + ) >= MaximumVariableSize + ) { + NotEnd = TRUE; + break; + } + + VariableNeededSize += OneItemNeededSize; + ItemIndex = GetNextNode (MappingDataBase, ItemIndex); + } + + if (NotEnd != 0) { + if (VariableNeededSize == sizeof (UINT32)) { + // + // If an individual EFI variable cannot contain a single Item, return error + // + return EFI_OUT_OF_RESOURCES; + } + } + + // + // VariableNeededSize is the most proper variable size, allocate variable buffer + // ItemIndex now points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize + // + VariableBuffer = AllocateZeroPool (VariableNeededSize); + ASSERT (VariableBuffer != NULL); + ASSERT ((UINTN) VariableBuffer % sizeof(UINTN) == 0); + + // + // Fill the variable buffer according to MappingDataBase + // + VariableIndex = VariableBuffer; + *(UINT32 *) VariableIndex = NotEnd; + VariableIndex += sizeof (UINT32); // pass NotEnd + // + // ItemIndex points to the next PLATFORM_OVERRIDE_ITEM which is not covered by VariableNeededSize + // + while (OverrideItemListIndex != ItemIndex){ + *(UINT32 *) VariableIndex = PLATFORM_OVERRIDE_ITEM_SIGNATURE; + VariableIndex += sizeof (UINT32); // pass SIGNATURE + + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + *(UINT32 *) VariableIndex = OverrideItem->DriverInfoNum; + VariableIndex += sizeof (UINT32); // pass DriverNum + + CopyMem (VariableIndex, OverrideItem->ControllerDevicePath, GetDevicePathSize (OverrideItem->ControllerDevicePath)); + VariableIndex += GetDevicePathSize (OverrideItem->ControllerDevicePath); // pass ControllerDevicePath + + // + // Align the VariableIndex since the controller device path may not be aligned + // + VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); + // + // Save the Driver Info List of this PLATFORM_OVERRIDE_ITEM + // + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + CopyMem (VariableIndex, DriverImageInfo->DriverImagePath, GetDevicePathSize (DriverImageInfo->DriverImagePath)); + VariableIndex += GetDevicePathSize (DriverImageInfo->DriverImagePath); // pass DriverImageDevicePath + // + // Align the VariableIndex since the driver image device path may not be aligned + // + VariableIndex += ((sizeof(UINT32) - ((UINTN) (VariableIndex))) & (sizeof(UINT32) - 1)); + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + } + + ASSERT (((UINTN)VariableIndex - (UINTN)VariableBuffer) == VariableNeededSize); + + if (NumIndex == 0) { + UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver"); + } else { + UnicodeSPrint (OverrideVariableName, sizeof (OverrideVariableName), L"PlatDriOver%d", NumIndex ); + } + + Status = gRT->SetVariable ( + OverrideVariableName, + &gEfiCallerIdGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + VariableNeededSize, + VariableBuffer + ); + ASSERT (!EFI_ERROR(Status)); + + NumIndex ++; + FreePool (VariableBuffer); + } + + return EFI_SUCCESS; +} + +/** + Get the first Binding protocol which has the specific image handle. + + @param ImageHandle The Image handle + @param BindingHandle The BindingHandle of the found Driver Binding protocol. + If Binding protocol is not found, it is set to NULL. + + @return Pointer into the Binding Protocol interface + @retval NULL The paramter is not valid or the binding protocol is not found. + +**/ +EFI_DRIVER_BINDING_PROTOCOL * +EFIAPI +GetBindingProtocolFromImageHandle ( + IN EFI_HANDLE ImageHandle, + OUT EFI_HANDLE *BindingHandle + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + EFI_DRIVER_BINDING_PROTOCOL *DriverBindingInterface; + + if (BindingHandle == NULL || ImageHandle == NULL) { + return NULL; + } + // + // Get all drivers which support driver binding protocol + // + DriverBindingHandleCount = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { + return NULL; + } + + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + DriverBindingInterface = NULL; + Status = gBS->OpenProtocol ( + DriverBindingHandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBindingInterface, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (DriverBindingInterface->ImageHandle == ImageHandle) { + *BindingHandle = DriverBindingHandleBuffer[Index]; + FreePool (DriverBindingHandleBuffer); + return DriverBindingInterface; + } + } + + // + // If no Driver Binding Protocol instance is found + // + FreePool (DriverBindingHandleBuffer); + *BindingHandle = NULL; + return NULL; +} + +/** + Return the current TPL. + + @return Current TPL + +**/ +EFI_TPL +GetCurrentTpl ( + VOID + ) +{ + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + gBS->RestoreTPL (Tpl); + + return Tpl; +} + + +/** + Retrieves the image handle of the platform override driver for a controller in + the system from the memory mapping database. + + @param ControllerHandle The device handle of the controller to check if + a driver override exists. + @param DriverImageHandle On input, the previously returnd driver image handle. + On output, a pointer to the next driver handle. + Passing in a pointer to NULL, will return the + first driver handle for ControllerHandle. + @param MappingDataBase Mapping database list entry pointer + @param CallerImageHandle The caller driver's image handle, for + UpdateFvFileDevicePath use. + + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not + a valid handle. Or DriverImagePath is not a + device path that was returned on a previous call + to GetDriverPath(). + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not + found. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_SUCCESS The driver override for ControllerHandle was + returned in DriverImagePath. + +**/ +EFI_STATUS +EFIAPI +GetDriverFromMapping ( + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE *DriverImageHandle, + IN LIST_ENTRY *MappingDataBase, + IN EFI_HANDLE CallerImageHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath; + BOOLEAN ControllerFound; + BOOLEAN ImageFound; + EFI_HANDLE *ImageHandleBuffer; + UINTN ImageHandleCount; + UINTN Index; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + EFI_HANDLE DriverBindingHandle; + BOOLEAN FoundLastReturned; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + DRIVER_IMAGE_INFO *DriverImageInfo; + LIST_ENTRY *OverrideItemListIndex; + LIST_ENTRY *ImageInfoListIndex; + EFI_DEVICE_PATH_PROTOCOL *TempDriverImagePath; + EFI_HANDLE ImageHandle; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + UINTN DevicePathSize; + + // + // Check that ControllerHandle is a valid handle + // + if (ControllerHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Get the device path of ControllerHandle + // + Status = gBS->HandleProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ControllerDevicePath + ); + if (EFI_ERROR (Status) || ControllerDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Search ControllerDevicePath in MappingDataBase + // + OverrideItem = NULL; + ControllerFound = FALSE; + DevicePathSize = GetDevicePathSize (ControllerDevicePath); + + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { + if (CompareMem ( + ControllerDevicePath, + OverrideItem->ControllerDevicePath, + DevicePathSize + ) == 0 + ) { + ControllerFound = TRUE; + break; + } + } + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + } + + if (!ControllerFound) { + return EFI_NOT_FOUND; + } + // + // Passing in a pointer to NULL, will return the first driver device path for ControllerHandle. + // Check whether the driverImagePath is not a device path that was returned on a previous call to GetDriverPath(). + // + if (*DriverImageHandle != NULL) { + if (*DriverImageHandle != OverrideItem->LastReturnedImageHandle) { + return EFI_INVALID_PARAMETER; + } + } + // + // The GetDriverPath() may be called recursively, because it use ConnectDevicePath() internally, + // so should check whether there is a dead loop. + // Here use a controller device path stack to record all processed controller device path during a GetDriverPath() call, + // and check the controller device path whether appear again during the GetDriverPath() call. + // + if (CheckExistInStack (OverrideItem->ControllerDevicePath)) { + // + // There is a dependecy dead loop if the ControllerDevicePath appear in stack twice + // + return EFI_UNSUPPORTED; + } + PushDevPathStack (OverrideItem->ControllerDevicePath); + + // + // Check every override driver, try to load and start them + // + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + if (DriverImageInfo->ImageHandle == NULL) { + // + // Skip if the image is unloadable or unstartable + // + if ((!DriverImageInfo->UnLoadable) && ((!DriverImageInfo->UnStartable))) { + TempDriverImagePath = DriverImageInfo->DriverImagePath; + // + // If the image device path contains an FV node, check the FV file device path is valid. + // If it is invalid, try to return the valid device path. + // FV address maybe changes for memory layout adjust from time to time, + // use this funciton could promise the FV file device path is right. + // + Status = UpdateFvFileDevicePath (&TempDriverImagePath, NULL, CallerImageHandle); + if (!EFI_ERROR (Status)) { + FreePool (DriverImageInfo->DriverImagePath); + DriverImageInfo->DriverImagePath = TempDriverImagePath; + } + // + // Get all Loaded Image protocol to check whether the driver image has been loaded and started + // + ImageFound = FALSE; + ImageHandleCount = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadedImageProtocolGuid, + NULL, + &ImageHandleCount, + &ImageHandleBuffer + ); + if (EFI_ERROR (Status) || (ImageHandleCount == 0)) { + return EFI_NOT_FOUND; + } + + for(Index = 0; Index < ImageHandleCount; Index ++) { + // + // Get the EFI Loaded Image Device Path Protocol + // + LoadedImageDevicePath = NULL; + Status = gBS->HandleProtocol ( + ImageHandleBuffer[Index], + &gEfiLoadedImageDevicePathProtocolGuid, + (VOID **) &LoadedImageDevicePath + ); + if (EFI_ERROR (Status)) { + // + // Maybe not all EFI_LOADED_IMAGE_DEVICE_PATH_PROTOCOL existed. + // + continue; + } + + DevicePathSize = GetDevicePathSize (DriverImageInfo->DriverImagePath); + if (DevicePathSize == GetDevicePathSize (LoadedImageDevicePath)) { + if (CompareMem ( + DriverImageInfo->DriverImagePath, + LoadedImageDevicePath, + GetDevicePathSize (LoadedImageDevicePath) + ) == 0 + ) { + ImageFound = TRUE; + break; + } + } + } + + if (ImageFound) { + // + // Find its related driver binding protocol + // Driver binding handle may be different with its driver's Image Handle. + // + DriverBindingHandle = NULL; + DriverBinding = GetBindingProtocolFromImageHandle ( + ImageHandleBuffer[Index], + &DriverBindingHandle + ); + ASSERT (DriverBinding != NULL); + DriverImageInfo->ImageHandle = ImageHandleBuffer[Index]; + } else if (GetCurrentTpl() <= TPL_CALLBACK){ + // + // The driver image has not been loaded and started. Try to load and start it now. + // Try to connect all device in the driver image path. + // + // Note: LoadImage() and StartImage() should be called under CALLBACK TPL in theory, but + // since many device need to be connected in CALLBACK level environment( e.g. Usb devices ) + // and the Fat and Patition driver can endure executing in CALLBACK level in fact, so here permit + // to use LoadImage() and StartImage() in CALLBACK TPL. + // + Status = ConnectDevicePath (DriverImageInfo->DriverImagePath); + // + // check whether it points to a PCI Option Rom image, + // and try to use bus override protocol to get its first option rom image driver + // + TempDriverImagePath = DriverImageInfo->DriverImagePath; + gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle); + // + // Get the Bus Specific Driver Override Protocol instance on the Controller Handle + // + Status = gBS->HandleProtocol( + Handle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID **) &BusSpecificDriverOverride + ); + if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) { + ImageHandle = NULL; + Status = BusSpecificDriverOverride->GetDriver ( + BusSpecificDriverOverride, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find its related driver binding protocol + // Driver binding handle may be different with its driver's Image handle + // + DriverBindingHandle = NULL; + DriverBinding = GetBindingProtocolFromImageHandle ( + ImageHandle, + &DriverBindingHandle + ); + ASSERT (DriverBinding != NULL); + DriverImageInfo->ImageHandle = ImageHandle; + } + } + // + // Skip if any device cannot be connected now, future passes through GetDriver() may be able to load that driver. + // Only file path media or FwVol Device Path Node remain if all device is connected + // + TempDriverImagePath = DriverImageInfo->DriverImagePath; + gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &TempDriverImagePath, &Handle); + if (((DevicePathType (TempDriverImagePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (TempDriverImagePath) == MEDIA_FILEPATH_DP)) || + (EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) TempDriverImagePath) != NULL) + ) { + // + // Try to load the driver + // + TempDriverImagePath = DriverImageInfo->DriverImagePath; + Status = gBS->LoadImage ( + FALSE, + CallerImageHandle, + TempDriverImagePath, + NULL, + 0, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + // + // Try to start the driver + // + Status = gBS->StartImage (ImageHandle, NULL, NULL); + if (EFI_ERROR (Status)){ + DriverImageInfo->UnStartable = TRUE; + DriverImageInfo->ImageHandle = NULL; + } else { + // + // Find its related driver binding protocol + // Driver binding handle may be different with its driver's Image handle + // + DriverBindingHandle = NULL; + DriverBinding = GetBindingProtocolFromImageHandle ( + ImageHandle, + &DriverBindingHandle + ); + ASSERT (DriverBinding != NULL); + DriverImageInfo->ImageHandle = ImageHandle; + } + } else { + DriverImageInfo->UnLoadable = TRUE; + DriverImageInfo->ImageHandle = NULL; + } + } + } + FreePool (ImageHandleBuffer); + } + } + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + // + // Finish try to load and start the override driver of a controller, popup the controller's device path + // + PopDevPathStack (NULL); + + // + // return the DriverImageHandle for ControllerHandle + // + FoundLastReturned = FALSE; + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + if (DriverImageInfo->ImageHandle != NULL) { + if ((*DriverImageHandle == NULL) || FoundLastReturned) { + // + // If DriverImageHandle is NULL, then we just need to return the first driver. + // If FoundLastReturned, this means we have just encountered the previously returned driver. + // For both cases, we just return the image handle of this driver. + // + OverrideItem->LastReturnedImageHandle = DriverImageInfo->ImageHandle; + *DriverImageHandle = DriverImageInfo->ImageHandle; + return EFI_SUCCESS; + } else if (*DriverImageHandle == DriverImageInfo->ImageHandle){ + // + // We have found the previously returned driver. + // + FoundLastReturned = TRUE; + } + } + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + + return EFI_NOT_FOUND; +} + + +/** + Check mapping database whether already has the mapping info which + records the input Controller to input DriverImage. + + @param ControllerDevicePath The controller device path is to be check. + @param DriverImageDevicePath The driver image device path is to be check. + @param MappingDataBase Mapping database list entry pointer + @param DriverInfoNum the controller's total override driver number + @param DriverImageNO The driver order number for the input DriverImage. + If the DriverImageDevicePath is NULL, DriverImageNO is not set. + + @retval EFI_INVALID_PARAMETER ControllerDevicePath or MappingDataBase is NULL. + @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or + DriverImageDevicePath is not found in the found DriverImage Info list. + @retval EFI_SUCCESS The controller's total override driver number and + input DriverImage's order number is correctly return. +**/ +EFI_STATUS +EFIAPI +CheckMapping ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath OPTIONAL, + IN LIST_ENTRY *MappingDataBase, + OUT UINT32 *DriverInfoNum OPTIONAL, + OUT UINT32 *DriverImageNO OPTIONAL + ) +{ + LIST_ENTRY *OverrideItemListIndex; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + LIST_ENTRY *ImageInfoListIndex; + DRIVER_IMAGE_INFO *DriverImageInfo; + BOOLEAN Found; + UINT32 ImageNO; + UINTN DevicePathSize; + + if (ControllerDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Search ControllerDevicePath in MappingDataBase + // + Found = FALSE; + OverrideItem = NULL; + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + DevicePathSize = GetDevicePathSize (ControllerDevicePath); + if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { + if (CompareMem ( + ControllerDevicePath, + OverrideItem->ControllerDevicePath, + DevicePathSize + ) == 0 + ) { + Found = TRUE; + break; + } + } + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + } + + if (!Found) { + // + // ControllerDevicePath is not in MappingDataBase + // + return EFI_NOT_FOUND; + } + + ASSERT (OverrideItem->DriverInfoNum != 0); + if (DriverInfoNum != NULL) { + *DriverInfoNum = OverrideItem->DriverInfoNum; + } + + // + // If DriverImageDevicePath is NULL, skip checking DriverImageDevicePath + // in the controller's Driver Image Info List + // + if (DriverImageDevicePath == NULL) { + return EFI_SUCCESS; + } + // + // return the DriverImageHandle for ControllerHandle + // + ImageNO = 0; + Found = FALSE; + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + ImageNO++; + DevicePathSize = GetDevicePathSize (DriverImageDevicePath); + if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) { + if (CompareMem ( + DriverImageDevicePath, + DriverImageInfo->DriverImagePath, + GetDevicePathSize (DriverImageInfo->DriverImagePath) + ) == 0 + ) { + Found = TRUE; + break; + } + } + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + + if (!Found) { + // + // DriverImageDevicePath is not found in the controller's Driver Image Info List + // + return EFI_NOT_FOUND; + } else { + if (DriverImageNO != NULL) { + *DriverImageNO = ImageNO; + } + return EFI_SUCCESS; + } +} + + +/** + Insert a driver image as a controller's override driver into the mapping database. + The driver image's order number is indicated by DriverImageNO. + + @param ControllerDevicePath The controller device path need to add a + override driver image item + @param DriverImageDevicePath The driver image device path need to be insert + @param MappingDataBase Mapping database list entry pointer + @param DriverImageNO The inserted order number. If this number is taken, + the larger available number will be used. + + @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or DriverImageDevicePath is NULL + or MappingDataBase is NULL + @retval EFI_ALREADY_STARTED The input Controller to input DriverImage has been + recorded into the mapping database. + @retval EFI_SUCCESS The Controller and DriverImage are inserted into + the mapping database successfully. + +**/ +EFI_STATUS +EFIAPI +InsertDriverImage ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, + IN LIST_ENTRY *MappingDataBase, + IN UINT32 DriverImageNO + ) +{ + EFI_STATUS Status; + LIST_ENTRY *OverrideItemListIndex; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + LIST_ENTRY *ImageInfoListIndex; + DRIVER_IMAGE_INFO *DriverImageInfo; + BOOLEAN Found; + UINT32 ImageNO; + UINTN DevicePathSize; + + if (ControllerDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + if (DriverImageDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If the driver is already in the controller's Driver Image Info List, + // just return EFI_ALREADY_STARTED. + // + Status = CheckMapping ( + ControllerDevicePath, + DriverImageDevicePath, + MappingDataBase, + NULL, + NULL + ); + if (Status == EFI_SUCCESS) { + return EFI_ALREADY_STARTED; + } + + // + // Search the input ControllerDevicePath in MappingDataBase + // + Found = FALSE; + OverrideItem = NULL; + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + DevicePathSize = GetDevicePathSize (ControllerDevicePath); + if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { + if (CompareMem ( + ControllerDevicePath, + OverrideItem->ControllerDevicePath, + DevicePathSize + ) == 0 + ) { + Found = TRUE; + break; + } + } + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + } + // + // If cannot find, this is a new controller item + // Add the Controller related PLATFORM_OVERRIDE_ITEM structrue in mapping data base + // + if (!Found) { + OverrideItem = AllocateZeroPool (sizeof (PLATFORM_OVERRIDE_ITEM)); + ASSERT (OverrideItem != NULL); + OverrideItem->Signature = PLATFORM_OVERRIDE_ITEM_SIGNATURE; + OverrideItem->ControllerDevicePath = DuplicateDevicePath (ControllerDevicePath); + InitializeListHead (&OverrideItem->DriverInfoList); + InsertTailList (MappingDataBase, &OverrideItem->Link); + } + + // + // Prepare the driver image related DRIVER_IMAGE_INFO structure. + // + DriverImageInfo = AllocateZeroPool (sizeof (DRIVER_IMAGE_INFO)); + ASSERT (DriverImageInfo != NULL); + DriverImageInfo->Signature = DRIVER_IMAGE_INFO_SIGNATURE; + DriverImageInfo->DriverImagePath = DuplicateDevicePath (DriverImageDevicePath); + // + // Find the driver image wanted order location + // + ImageNO = 0; + Found = FALSE; + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + if (ImageNO == (DriverImageNO - 1)) { + // + // find the wanted order location, insert it + // + InsertTailList (ImageInfoListIndex, &DriverImageInfo->Link); + OverrideItem->DriverInfoNum ++; + Found = TRUE; + break; + } + ImageNO++; + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + } + + if (!Found) { + // + // if not find the wanted order location, add it as last item of the controller mapping item + // + InsertTailList (&OverrideItem->DriverInfoList, &DriverImageInfo->Link); + OverrideItem->DriverInfoNum ++; + } + + return EFI_SUCCESS; +} + + +/** + Delete a controller's override driver from the mapping database. + + @param ControllerDevicePath The controller device path will be deleted + when all drivers images on it are removed. + @param DriverImageDevicePath The driver image device path will be delete. + If NULL, all driver image will be delete. + @param MappingDataBase Mapping database list entry pointer + + @retval EFI_INVALID_PARAMETER ControllerDevicePath is NULL, or MappingDataBase is NULL + @retval EFI_NOT_FOUND ControllerDevicePath is not found in MappingDataBase or + DriverImageDevicePath is not found in the found DriverImage Info list. + @retval EFI_SUCCESS Delete the specified driver successfully. + +**/ +EFI_STATUS +EFIAPI +DeleteDriverImage ( + IN EFI_DEVICE_PATH_PROTOCOL *ControllerDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImageDevicePath, + IN LIST_ENTRY *MappingDataBase + ) +{ + EFI_STATUS Status; + LIST_ENTRY *OverrideItemListIndex; + PLATFORM_OVERRIDE_ITEM *OverrideItem; + LIST_ENTRY *ImageInfoListIndex; + DRIVER_IMAGE_INFO *DriverImageInfo; + BOOLEAN Found; + UINTN DevicePathSize; + + if (ControllerDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (MappingDataBase == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If ControllerDevicePath is not found in mapping database, return EFI_NOT_FOUND. + // + Status = CheckMapping ( + ControllerDevicePath, + DriverImageDevicePath, + MappingDataBase, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Search ControllerDevicePath in MappingDataBase + // + Found = FALSE; + OverrideItem = NULL; + OverrideItemListIndex = GetFirstNode (MappingDataBase); + while (!IsNull (MappingDataBase, OverrideItemListIndex)) { + OverrideItem = CR(OverrideItemListIndex, PLATFORM_OVERRIDE_ITEM, Link, PLATFORM_OVERRIDE_ITEM_SIGNATURE); + DevicePathSize = GetDevicePathSize (ControllerDevicePath); + if (DevicePathSize == GetDevicePathSize (OverrideItem->ControllerDevicePath)) { + if (CompareMem ( + ControllerDevicePath, + OverrideItem->ControllerDevicePath, + DevicePathSize + ) == 0 + ) { + Found = TRUE; + break; + } + } + OverrideItemListIndex = GetNextNode (MappingDataBase, OverrideItemListIndex); + } + + ASSERT (Found); + ASSERT (OverrideItem->DriverInfoNum != 0); + + Found = FALSE; + ImageInfoListIndex = GetFirstNode (&OverrideItem->DriverInfoList); + while (!IsNull (&OverrideItem->DriverInfoList, ImageInfoListIndex)) { + DriverImageInfo = CR(ImageInfoListIndex, DRIVER_IMAGE_INFO, Link, DRIVER_IMAGE_INFO_SIGNATURE); + ImageInfoListIndex = GetNextNode (&OverrideItem->DriverInfoList, ImageInfoListIndex); + if (DriverImageDevicePath != NULL) { + // + // Search for the specified DriverImageDevicePath and remove it, then break. + // + DevicePathSize = GetDevicePathSize (DriverImageDevicePath); + if (DevicePathSize == GetDevicePathSize (DriverImageInfo->DriverImagePath)) { + if (CompareMem ( + DriverImageDevicePath, + DriverImageInfo->DriverImagePath, + GetDevicePathSize (DriverImageInfo->DriverImagePath) + ) == 0 + ) { + Found = TRUE; + FreePool(DriverImageInfo->DriverImagePath); + RemoveEntryList (&DriverImageInfo->Link); + OverrideItem->DriverInfoNum --; + break; + } + } + } else { + // + // Remove all existing driver image info entries, so no break here. + // + Found = TRUE; + FreePool(DriverImageInfo->DriverImagePath); + RemoveEntryList (&DriverImageInfo->Link); + OverrideItem->DriverInfoNum --; + } + } + + // + // Confirm all driver image info entries have been removed, + // if DriverImageDevicePath is NULL. + // + if (DriverImageDevicePath == NULL) { + ASSERT (OverrideItem->DriverInfoNum == 0); + } + // + // If Override Item has no driver image info entry, then delete this item. + // + if (OverrideItem->DriverInfoNum == 0) { + FreePool(OverrideItem->ControllerDevicePath); + RemoveEntryList (&OverrideItem->Link); + FreePool (OverrideItem); + } + + if (!Found) { + // + // DriverImageDevicePath is not NULL and cannot be found in the controller's + // driver image info list. + // + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h new file mode 100644 index 0000000000..2d73d0ee6f --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatOverMngr.h @@ -0,0 +1,73 @@ +/** @file + + The defintions are required both by Source code and Vfr file. + The PLAT_OVER_MNGR_DATA structure, form guid and Ifr question ID are defined. + +Copyright (c) 2007 - 2008, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef _PLAT_OVER_MNGR_H_ +#define _PLAT_OVER_MNGR_H_ + +#define PLAT_OVER_MNGR_GUID \ + { \ + 0x8614567d, 0x35be, 0x4415, {0x8d, 0x88, 0xbd, 0x7d, 0xc, 0x9c, 0x70, 0xc0} \ + } + +// +// The max number of the supported driver list. +// +#define MAX_CHOICE_NUM 0x00ff +#define UPDATE_DATA_SIZE 0x1000 + +#define FORM_ID_DEVICE 0x1100 +#define FORM_ID_DRIVER 0x1200 +#define FORM_ID_ORDER 0x1500 + +#define KEY_VALUE_DEVICE_OFFSET 0x0100 +#define KEY_VALUE_DEVICE_MAX (KEY_VALUE_DEVICE_OFFSET + MAX_CHOICE_NUM) + +#define KEY_VALUE_DEVICE_REFRESH 0x1234 +#define KEY_VALUE_DEVICE_FILTER 0x1235 +#define KEY_VALUE_DEVICE_CLEAR 0x1236 + +#define KEY_VALUE_DRIVER_GOTO_PREVIOUS 0x1300 +#define KEY_VALUE_DRIVER_GOTO_ORDER 0x1301 + +#define KEY_VALUE_ORDER_GOTO_PREVIOUS 0x2000 +#define KEY_VALUE_ORDER_SAVE_AND_EXIT 0x1800 + +#define VARSTORE_ID_PLAT_OVER_MNGR 0x1000 + +#define LABEL_END 0xffff + +typedef struct { + UINT8 DriSelection[MAX_CHOICE_NUM]; + UINT8 DriOrder[MAX_CHOICE_NUM]; + UINT8 PciDeviceFilter; +} PLAT_OVER_MNGR_DATA; + +// +// Field offset of structure PLAT_OVER_MNGR_DATA +// +#define VAR_OFFSET(Field) ((UINTN) &(((PLAT_OVER_MNGR_DATA *) 0)->Field)) +#define DRIVER_SELECTION_VAR_OFFSET (VAR_OFFSET (DriSelection)) +#define DRIVER_ORDER_VAR_OFFSET (VAR_OFFSET (DriOrder)) + +// +// Tool automatic generated Question Id start from 1 +// In order to avoid to conflict them, the Driver Selection and Order QuestionID offset is defined from 0x0500. +// +#define QUESTION_ID_OFFSET 0x0500 +#define DRIVER_SELECTION_QUESTION_ID (VAR_OFFSET (DriSelection) + QUESTION_ID_OFFSET) +#define DRIVER_ORDER_QUESTION_ID (VAR_OFFSET (DriOrder) + QUESTION_ID_OFFSET) + +#endif diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c deleted file mode 100644 index 64e9a4d64d..0000000000 --- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverride.c +++ /dev/null @@ -1,212 +0,0 @@ -/** @file - -Copyright (c) 2007 - 2009, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -**/ - -#include - -#include -#include -#include -#include -#include -#include - -LIST_ENTRY mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase); -BOOLEAN mEnvironmentVariableRead = FALSE; -EFI_HANDLE mCallerImageHandle = NULL; - -/** - Retrieves the image handle of the platform override driver for a controller in the system. - - @param This A pointer to the - EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL instance. - @param ControllerHandle The device handle of the controller to check if a - driver override exists. - @param DriverImageHandle On input, a pointer to the previous driver image - handle returned by GetDriver(). On output, a - pointer to the next driver image handle. Passing - in a NULL, will return the first driver image - handle for ControllerHandle. - - @retval EFI_SUCCESS The driver override for ControllerHandle was - returned in DriverImageHandle. - @retval EFI_NOT_FOUND A driver override for ControllerHandle was not - found. - @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a - valid handle. DriverImageHandle is not a handle - that was returned on a previous call to - GetDriver(). - -**/ -EFI_STATUS -EFIAPI -GetDriver ( - IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN OUT EFI_HANDLE *DriverImageHandle - ) -{ - EFI_STATUS Status; - - // - // Check that ControllerHandle is a valid handle - // - if (ControllerHandle == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // Read the environment variable(s) that contain the override mappings from Controller Device Path to - // a set of Driver Device Paths, and initialize in memory database of the overrides that map Controller - // Device Paths to an ordered set of Driver Device Paths and Driver Handles. This action is only performed - // once and finished in first call. - // - if (!mEnvironmentVariableRead) { - mEnvironmentVariableRead = TRUE; - - Status = InitOverridesMapping (&mMappingDataBase); - if (EFI_ERROR (Status)){ - DEBUG ((DEBUG_ERROR, "The status to Get Platform Driver Override Variable is %r\n", Status)); - InitializeListHead (&mMappingDataBase); - return EFI_NOT_FOUND; - } - } - - // - // if the environment variable does not exist, just return not found - // - if (IsListEmpty (&mMappingDataBase)) { - return EFI_NOT_FOUND; - } - - return GetDriverFromMapping ( - ControllerHandle, - DriverImageHandle, - &mMappingDataBase, - mCallerImageHandle - ); -} - -/** - Retrieves the device path of the platform override driver for a controller in the system. - This driver doesn't support this API. - - @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ - PROTOCOL instance. - @param ControllerHandle The device handle of the controller to check if a driver override - exists. - @param DriverImagePath On input, a pointer to the previous driver device path returned by - GetDriverPath(). On output, a pointer to the next driver - device path. Passing in a pointer to NULL, will return the first - driver device path for ControllerHandle. - - @retval EFI_UNSUPPORTED -**/ -EFI_STATUS -EFIAPI -GetDriverPath ( - IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath - ) -{ - return EFI_UNSUPPORTED; -} - - -/** - Used to associate a driver image handle with a device path that was returned on a prior call to the - GetDriverPath() service. This driver image handle will then be available through the - GetDriver() service. This driver doesn't support this API. - - @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ - PROTOCOL instance. - @param ControllerHandle The device handle of the controller. - @param DriverImagePath A pointer to the driver device path that was returned in a prior - call to GetDriverPath(). - @param DriverImageHandle The driver image handle that was returned by LoadImage() - when the driver specified by DriverImagePath was loaded - into memory. - - @retval EFI_UNSUPPORTED -**/ -EFI_STATUS -EFIAPI -DriverLoaded ( - IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, - IN EFI_HANDLE ControllerHandle, - IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath, - IN EFI_HANDLE DriverImageHandle - ) -{ - return EFI_UNSUPPORTED; -} - -EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL mPlatformDriverOverride = { - GetDriver, - GetDriverPath, - DriverLoaded -}; - -/** - Platform Driver Override driver entry point, install the Platform Driver Override Protocol - - @param ImageHandle ImageHandle of the loaded driver. - @param SystemTable Pointer to the EFI System Table. - - @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM Driver, - or UEFI Driver exited normally. - @retval EFI_ALREADY_STARTED A protocol instance has been installed. Not need install again. -**/ -EFI_STATUS -EFIAPI -PlatformDriverOverrideEntry ( - IN EFI_HANDLE ImageHandle, - IN EFI_SYSTEM_TABLE *SystemTable - ) -{ - EFI_HANDLE Handle; - EFI_STATUS Status; - VOID *Instance; - - mCallerImageHandle = ImageHandle; - - // - // According to UEFI spec, there can be at most a single instance - // in the system of the EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL. - // So here we check the existence. - // - Status = gBS->LocateProtocol ( - &gEfiPlatformDriverOverrideProtocolGuid, - NULL, - &Instance - ); - // - // If there was no error, assume there is an installation and return error - // - if (!EFI_ERROR (Status)) { - return EFI_ALREADY_STARTED; - } - - // - // Install platform driver override protocol - // - Handle = NULL; - Status = gBS->InstallProtocolInterface ( - &Handle, - &gEfiPlatformDriverOverrideProtocolGuid, - EFI_NATIVE_INTERFACE, - &mPlatformDriverOverride - ); - ASSERT_EFI_ERROR (Status); - return EFI_SUCCESS; -} diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf index 855fb82a59..59bc3dfed0 100644 --- a/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/PlatformDriOverrideDxe.inf @@ -1,9 +1,21 @@ #/** @file -# This driver produces UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL if this protocol doesn't exist. -# It doesn't install again if this protocol exists. -# It only implements one interface GetDriver of PLATFORM_DRIVER_OVERRIDE_PROTOCOL protocol -# and doesn't support other two interfaces GetDriverPath, DriverLoaded. +# This driver produces UEFI PLATFORM_DRIVER_OVERRIDE_PROTOCOL if this protocol doesn't exist. +# It doesn't install again if this protocol exists. +# It only implements one interface GetDriver of PLATFORM_DRIVER_OVERRIDE_PROTOCOL protocol +# and doesn't support other two interfaces GetDriverPath, DriverLoaded. # +# This driver also offers an UI interface in device manager to let user configure +# platform override protocol to override the default algorithm for matching +# drivers to controllers. +# +# The main flow: +# 1. It dynamicly locate all controller device path. +# 2. It dynamicly locate all drivers which support binding protocol. +# 3. It export and dynamicly update two menu to let user select the +# mapping between drivers to controllers. +# 4. It save all the mapping info in NV variables for the following boot, +# which will be consumed by GetDriver API of the produced the platform override protocol. +# # Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved. # # All rights reserved. This program and the accompanying materials @@ -18,11 +30,12 @@ [Defines] INF_VERSION = 0x00010005 - BASE_NAME = PlatformDriOverrideDxe + BASE_NAME = PlatDriOverrideDxe FILE_GUID = 35034CE2-A6E5-4fb4-BABE-A0156E9B2549 - MODULE_TYPE = UEFI_DRIVER + MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 - ENTRY_POINT = PlatformDriverOverrideEntry + ENTRY_POINT = PlatDriOverrideDxeInit + UNLOAD_IMAGE = PlatDriOverrideDxeUnload # # The following information is for reference only and not required by the build tools. @@ -31,7 +44,12 @@ # [Sources.common] - PlatformDriOverride.c + VfrStrings.uni + Vfr.vfr + PlatDriOverrideDxe.c + PlatOverMngr.h + PlatDriOverrideLib.c + InternalPlatDriOverrideDxe.h [Packages] MdePkg/MdePkg.dec @@ -39,11 +57,43 @@ [LibraryClasses] BaseLib - UefiDriverEntryPoint DebugLib - PlatformDriverOverrideLib + UefiLib + UefiDriverEntryPoint UefiBootServicesTableLib + HiiLib + BaseMemoryLib + MemoryAllocationLib + DevicePathLib + DxeServicesTableLib + UefiRuntimeServicesTableLib + PrintLib + +[Guids] + ## This GUID C Name is not required for build since it is from UefiLib and not directly used by this module source. + ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"PlatformLang" this variable specifies the platform supported language string (RFC 4646 format) + ## gEfiGlobalVariableGuid ## SOMETIMES_CONSUMED ## Variable:L"Lang" this variable specifies the platform supported language string (ISO 639-2 format) + ## + # There could be more than one variables, from PlatDriOver, PlatDriOver1, PlatDriOver2,... + # + # gEfiCallerIdGuid ## Private ## Variable:L"PlatDriOver" + gEfiIfrTianoGuid ## CONSUMES ## Guid [Protocols] - gEfiPlatformDriverOverrideProtocolGuid ## PRODUCED - \ No newline at end of file + gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentName2Protocol exists) + gEfiComponentNameProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name if ComponentNameProtocol exists and ComponentName2Protocol doesn't exist) + gEfiFirmwareVolume2ProtocolGuid ## SOMETIMES_CONSUMED (Get Driver Name from EFI UI section if ComponentName2Protocol and ComponentNameProtocol don't exist) + gEfiPciIoProtocolGuid ## SOMETIMES_CONSUMED (Find the PCI device if PciIo protocol is installed) + gEfiBusSpecificDriverOverrideProtocolGuid ## SOMETIMES_CONSUMED (Check whether the PCI device contains one or more efi drivers in its option rom by this protocol) + + gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMED + gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMED + gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the drivers in the second page that support DriverBindingProtocol, LoadedImageProtocol and LoadedImageDevicePathProtocol) + gEfiDevicePathProtocolGuid ## SOMETIMES_CONSUMED (Show the controller device in the first page that support DevicePathProtocol) + + gEfiHiiDatabaseProtocolGuid ## CONSUMED + gEfiFormBrowser2ProtocolGuid ## CONSUMED + gEfiHiiConfigRoutingProtocolGuid ## CONSUMED + gEfiHiiConfigAccessProtocolGuid ## PRODUCED + gEfiDevicePathToTextProtocolGuid ## CONSUMED + gEfiPlatformDriverOverrideProtocolGuid ## PRODUCED diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr b/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr new file mode 100644 index 0000000000..f00a51007b --- /dev/null +++ b/MdeModulePkg/Universal/PlatformDriOverrideDxe/Vfr.vfr @@ -0,0 +1,109 @@ +// *++ +// +// Copyright (c) 2009, Intel Corporation +// All rights reserved. This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// Module Name: +// +// Vfr.vfr +// +// Abstract: +// +// Platform driver Override manager formset +// +// +// --*/ + +#include "PlatOverMngr.h" + +#define EFI_DISK_DEVICE_CLASS 0x01 + +formset + guid = PLAT_OVER_MNGR_GUID, + title = STRING_TOKEN(STR_ENTRY_TITLE), + help = STRING_TOKEN(STR_TITLE_HELP), + class = EFI_DISK_DEVICE_CLASS, + subclass = 0xff, + + varstore PLAT_OVER_MNGR_DATA, + varid = VARSTORE_ID_PLAT_OVER_MNGR, + name = Data, + guid = PLAT_OVER_MNGR_GUID; + + form formid = FORM_ID_DEVICE, + title = STRING_TOKEN(STR_TITLE); + + text + help = STRING_TOKEN(STR_FIRST_REFRESH_HELP), + text = STRING_TOKEN(STR_FIRST_REFRESH), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_DEVICE_REFRESH; + + checkbox varid = Data.PciDeviceFilter, + prompt = STRING_TOKEN(STR_PCI_DEVICE_FILTER_PROMPT), + help = STRING_TOKEN(STR_PCI_DEVICE_FILTER_HELP), + flags = INTERACTIVE, + key = KEY_VALUE_DEVICE_FILTER, + endcheckbox; + + label FORM_ID_DEVICE; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_ID_DEVICE, + prompt = STRING_TOKEN(STR_CLEAR_ALL), + help = STRING_TOKEN(STR_CLEAR_ALL_HELP), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_VALUE_DEVICE_CLEAR; + endform; + + form formid = FORM_ID_DRIVER, + title = STRING_TOKEN(STR_TITLE); + + goto FORM_ID_DEVICE, + prompt = STRING_TOKEN(STR_GOTO_PREVIOUS), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_DRIVER_GOTO_PREVIOUS; + + goto FORM_ID_ORDER, + prompt = STRING_TOKEN(STR_TITLE_ORDER), + help = STRING_TOKEN(STR_TITLE_ORDER_HELP), + flags = INTERACTIVE, + key = KEY_VALUE_DRIVER_GOTO_ORDER; + + label FORM_ID_DRIVER; + label LABEL_END; + + endform; + + form formid = FORM_ID_ORDER, + title = STRING_TOKEN(STR_TITLE); + + goto FORM_ID_DRIVER, + prompt = STRING_TOKEN(STR_GOTO_PREVIOUS), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE, + key = KEY_VALUE_ORDER_GOTO_PREVIOUS; + + label FORM_ID_ORDER; + label LABEL_END; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_ID_ORDER, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_VALUE_ORDER_SAVE_AND_EXIT; + endform; + +endformset; diff --git a/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni b/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni new file mode 100644 index 0000000000..c30fb5c4de Binary files /dev/null and b/MdeModulePkg/Universal/PlatformDriOverrideDxe/VfrStrings.uni differ -- cgit v1.2.3