- stardard -> standard - doule -> double - defalut -> default - Pacakge -> Package - globa -> global - responsiblity -> responsibility - outputed -> outputted - specifiecd -> specified - Resuts -> Results - the a -> a - suported -> supported - assocated -> associated - TURE -> TRUE - successfull -> successfully - excute -> execute - reseting -> resetting - Retrive -> Retrieve - funciton -> function - paramter -> parameter - dependecy -> dependency - boundry -> boundary - permenantly -> permanently Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Gary Lin <glin@suse.com> Reviewed-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
		
			
				
	
	
		
			1751 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1751 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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 - 2015, Intel Corporation. All rights reserved.<BR>
 | 
						|
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
 | 
						|
//
 | 
						|
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;
 | 
						|
UINTN                        mDriverImageHandleCount;
 | 
						|
EFI_STRING_ID                *mDriverImageToken;
 | 
						|
EFI_DEVICE_PATH_PROTOCOL     **mControllerDevicePathProtocol;
 | 
						|
UINTN                        mSelectedDriverImageNum;
 | 
						|
UINTN                        mLastSavedDriverImageNum;
 | 
						|
UINT16                       mCurrentPage;
 | 
						|
EFI_CALLBACK_INFO           *mCallbackInfo;
 | 
						|
BOOLEAN                     *mDriSelection;
 | 
						|
UINTN                        mMaxDeviceCount;
 | 
						|
 | 
						|
HII_VENDOR_DEVICE_PATH  mHiiVendorDevicePath = {
 | 
						|
  {
 | 
						|
    {
 | 
						|
      HARDWARE_DEVICE_PATH,
 | 
						|
      HW_VENDOR_DP,
 | 
						|
      {
 | 
						|
        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
 | 
						|
        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
 | 
						|
      }
 | 
						|
    },
 | 
						|
    PLAT_OVER_MNGR_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.
 | 
						|
 | 
						|
  @param    DevPath     Given device path instance
 | 
						|
  
 | 
						|
  @return   Converted string from given device path.
 | 
						|
  @retval   L"?" Converting failed.
 | 
						|
**/
 | 
						|
CHAR16 *
 | 
						|
DevicePathToStr (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16                          *Text;
 | 
						|
  Text = ConvertDevicePathToText (
 | 
						|
           DevPath,
 | 
						|
           FALSE,
 | 
						|
           TRUE
 | 
						|
           );
 | 
						|
  if (Text == NULL) {
 | 
						|
    Text = AllocateCopyPool (sizeof (L"?"), L"?");
 | 
						|
    ASSERT (Text != NULL);
 | 
						|
  }
 | 
						|
 | 
						|
  return Text;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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.
 | 
						|
  //
 | 
						|
  GetEfiGlobalVariable2 (VariableName, (VOID**)&Language, NULL);
 | 
						|
  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;
 | 
						|
  UINTN                                     NewStrSize;
 | 
						|
  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,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    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;
 | 
						|
  }
 | 
						|
 | 
						|
  mMaxDeviceCount = DevicePathHandleCount;
 | 
						|
  mControllerDevicePathProtocol = AllocateZeroPool (DevicePathHandleCount * sizeof (EFI_DEVICE_PATH_PROTOCOL *));
 | 
						|
  ASSERT (mControllerDevicePathProtocol != NULL);
 | 
						|
  mControllerToken = AllocateZeroPool (DevicePathHandleCount * sizeof (EFI_STRING_ID));
 | 
						|
  ASSERT (mControllerToken != NULL);
 | 
						|
 | 
						|
  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);
 | 
						|
    NewStrSize = Len + StrSize (L"--");
 | 
						|
    NewString = AllocateZeroPool (NewStrSize);
 | 
						|
    ASSERT (NewString != NULL);
 | 
						|
    if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {
 | 
						|
      StrCatS (NewString, NewStrSize/sizeof(CHAR16), L"--");
 | 
						|
    } else {
 | 
						|
      StrCatS (NewString, NewStrSize/sizeof(CHAR16), L"**");
 | 
						|
    }
 | 
						|
    StrCatS (NewString, NewStrSize/sizeof(CHAR16), 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,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    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 parameter 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;
 | 
						|
  UINTN                                     NewStrSize;
 | 
						|
  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;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL                 **DriverImageProtocol;
 | 
						|
  EFI_STRING_ID                             *DriverImageFilePathToken;
 | 
						|
  UINT8                                     CheckFlags;
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 >= 0 && 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,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    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;
 | 
						|
  }
 | 
						|
 | 
						|
  mDriverImageToken = AllocateZeroPool (DriverImageHandleCount * sizeof (EFI_STRING_ID));
 | 
						|
  ASSERT (mDriverImageToken != NULL);
 | 
						|
  mDriSelection = AllocateZeroPool (DriverImageHandleCount * sizeof (BOOLEAN));
 | 
						|
  ASSERT (mDriSelection != NULL);
 | 
						|
 | 
						|
  DriverImageProtocol = AllocateZeroPool (DriverImageHandleCount * sizeof (EFI_LOADED_IMAGE_PROTOCOL *));
 | 
						|
  ASSERT (DriverImageProtocol != NULL);
 | 
						|
  DriverImageFilePathToken = AllocateZeroPool (DriverImageHandleCount * sizeof (EFI_STRING_ID));
 | 
						|
  ASSERT (DriverImageFilePathToken != NULL);
 | 
						|
 | 
						|
  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)) {
 | 
						|
      mDriSelection[Index] = FALSE;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
    DriverImageProtocol[Index] = LoadedImage;
 | 
						|
    //
 | 
						|
    // Find its related driver binding protocol
 | 
						|
    //
 | 
						|
    DriverBindingHandle = GetDriverBindingHandleFromImageHandle (mDriverImageHandleBuffer[Index]);
 | 
						|
    if (DriverBindingHandle == NULL) {
 | 
						|
      mDriSelection[Index] = FALSE;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get the EFI Loaded Image Device Path Protocol
 | 
						|
    //
 | 
						|
    LoadedImageDevicePath = NULL;
 | 
						|
    Status = gBS->HandleProtocol (
 | 
						|
                        mDriverImageHandleBuffer[Index],
 | 
						|
                        &gEfiLoadedImageDevicePathProtocolGuid,
 | 
						|
                        (VOID **) &LoadedImageDevicePath
 | 
						|
                        );
 | 
						|
    if (LoadedImageDevicePath == NULL) {
 | 
						|
      mDriSelection[Index] = FALSE;
 | 
						|
      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) {
 | 
						|
          mDriSelection[Index] = FALSE;
 | 
						|
          continue;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        mDriSelection[Index] = FALSE;
 | 
						|
        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
 | 
						|
    //
 | 
						|
    NewStrSize = StrSize (DriverName);
 | 
						|
    NewString = AllocateZeroPool (NewStrSize);
 | 
						|
    ASSERT (NewString != NULL); 
 | 
						|
    if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {
 | 
						|
      mDriSelection[Index] = FALSE;
 | 
						|
    } else {
 | 
						|
      mDriSelection[Index] = TRUE;
 | 
						|
      mLastSavedDriverImageNum++;
 | 
						|
    }
 | 
						|
    StrCatS (NewString, NewStrSize/sizeof(CHAR16), 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);
 | 
						|
 | 
						|
    NewStrSize = StrSize (DriverName);
 | 
						|
    NewString = AllocateZeroPool (NewStrSize);
 | 
						|
    ASSERT (NewString != NULL); 
 | 
						|
    StrCatS (NewString, NewStrSize/sizeof(CHAR16), DriverName);
 | 
						|
    NewStringHelpToken = HiiSetString (Private->RegisteredHandle, DriverImageFilePathToken[Index], NewString, NULL);
 | 
						|
    ASSERT (NewStringHelpToken != 0);
 | 
						|
    DriverImageFilePathToken[Index] = NewStringHelpToken;
 | 
						|
    FreePool (NewString);
 | 
						|
    FreePool (DriverName);
 | 
						|
 | 
						|
    CheckFlags        = 0;
 | 
						|
    if (mDriSelection[Index]) {
 | 
						|
      CheckFlags |= EFI_IFR_CHECKBOX_DEFAULT;
 | 
						|
    }
 | 
						|
 | 
						|
    HiiCreateCheckBoxOpCode (
 | 
						|
      StartOpCodeHandle,
 | 
						|
      (UINT16) (KEY_VALUE_DRIVER_OFFSET + Index),
 | 
						|
      0,
 | 
						|
      0,
 | 
						|
      NewStringToken,
 | 
						|
      NewStringHelpToken,
 | 
						|
      EFI_IFR_FLAG_CALLBACK,
 | 
						|
      CheckFlags,
 | 
						|
      NULL
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update second page form
 | 
						|
  //
 | 
						|
  HiiUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_DRIVER,
 | 
						|
    StartOpCodeHandle, // Label FORM_ID_DRIVER
 | 
						|
    EndOpCodeHandle    // LABEL_END
 | 
						|
    );
 | 
						|
 | 
						|
  HiiFreeOpCodeHandle (StartOpCodeHandle);
 | 
						|
  HiiFreeOpCodeHandle (EndOpCodeHandle);
 | 
						|
 | 
						|
  if (DriverImageProtocol != NULL) {
 | 
						|
    FreePool (DriverImageProtocol);
 | 
						|
  }
 | 
						|
 | 
						|
  if (DriverImageFilePathToken != NULL) {
 | 
						|
    FreePool (DriverImageFilePathToken);
 | 
						|
  }
 | 
						|
 | 
						|
  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,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_ORDER,
 | 
						|
    StartOpCodeHandle,
 | 
						|
    EndOpCodeHandle
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Check how many drivers have been selected
 | 
						|
  //
 | 
						|
  SelectedDriverImageNum = 0;
 | 
						|
  for (Index = 0; Index < mDriverImageHandleCount; Index++) {
 | 
						|
    if (mDriSelection[Index]) {
 | 
						|
      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 (mDriSelection[Index]) {
 | 
						|
      //
 | 
						|
      // 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,
 | 
						|
    &gPlatformOverridesManagerGuid,
 | 
						|
    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
 | 
						|
CommitChanges (
 | 
						|
  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 <ConfigRequest> 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 <ConfigAltResp> 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 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;
 | 
						|
  EFI_STRING                       ConfigRequestHdr;
 | 
						|
  EFI_STRING                       ConfigRequest;
 | 
						|
  BOOLEAN                          AllocatedRequest;
 | 
						|
  UINTN                            Size;
 | 
						|
  UINTN                            BufferSize;
 | 
						|
 | 
						|
  if (Progress == NULL || Results == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  *Progress = Request;
 | 
						|
  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gPlatformOverridesManagerGuid, mVariableName)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  ConfigRequestHdr = NULL;
 | 
						|
  ConfigRequest    = NULL;
 | 
						|
  Size             = 0;
 | 
						|
  AllocatedRequest = FALSE;
 | 
						|
 | 
						|
  Private          = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
  HiiConfigRouting = Private->HiiConfigRouting;
 | 
						|
  ConfigRequest = Request;
 | 
						|
  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
 | 
						|
    //
 | 
						|
    // Request has no request element, construct full request string.
 | 
						|
    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
 | 
						|
    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
 | 
						|
    //
 | 
						|
    ConfigRequestHdr = HiiConstructConfigHdr (&gPlatformOverridesManagerGuid, mVariableName, Private->DriverHandle);
 | 
						|
    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
 | 
						|
    ConfigRequest = AllocateZeroPool (Size);
 | 
						|
    ASSERT (ConfigRequest != NULL);
 | 
						|
    AllocatedRequest = TRUE;
 | 
						|
    BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
 | 
						|
    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
 | 
						|
    FreePool (ConfigRequestHdr);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert buffer data to <ConfigResp> by helper function BlockToConfig()
 | 
						|
  //
 | 
						|
  Status = HiiConfigRouting->BlockToConfig (
 | 
						|
                                HiiConfigRouting,
 | 
						|
                                ConfigRequest,
 | 
						|
                                (UINT8 *) &Private->FakeNvData,
 | 
						|
                                sizeof (PLAT_OVER_MNGR_DATA),
 | 
						|
                                Results,
 | 
						|
                                Progress
 | 
						|
                                );
 | 
						|
 | 
						|
  //
 | 
						|
  // Free the allocated config request string.
 | 
						|
  //
 | 
						|
  if (AllocatedRequest) {
 | 
						|
    FreePool (ConfigRequest);
 | 
						|
    ConfigRequest = NULL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Set Progress string to the original request string.
 | 
						|
  //
 | 
						|
  if (Request == NULL) {
 | 
						|
    *Progress = NULL;
 | 
						|
  } else if (StrStr (Request, L"OFFSET") == NULL) {
 | 
						|
    *Progress = Request + StrLen (Request);
 | 
						|
  }
 | 
						|
 | 
						|
  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 <ConfigRequest> 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;
 | 
						|
  EFI_STATUS                                Status;
 | 
						|
 | 
						|
  if (Configuration == NULL || Progress == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
  *Progress = Configuration;
 | 
						|
 | 
						|
  if (!HiiIsConfigHdrMatch (Configuration, &gPlatformOverridesManagerGuid, mVariableName)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
  
 | 
						|
  *Progress = Configuration + StrLen (Configuration);
 | 
						|
  Private    = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
  FakeNvData = &Private->FakeNvData;
 | 
						|
  if (!HiiGetBrowserData (&gPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {
 | 
						|
    //
 | 
						|
    // FakeNvData can't be got from SetupBrowser, which doesn't need to be set.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EFI_SUCCESS;
 | 
						|
 | 
						|
  if (mCurrentPage == FORM_ID_ORDER) {
 | 
						|
    KeyValue = KEY_VALUE_ORDER_SAVE_AND_EXIT;
 | 
						|
    Status = CommitChanges (Private, KeyValue, FakeNvData);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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 <ConfigRequest> 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;
 | 
						|
 | 
						|
  if ((Action != EFI_BROWSER_ACTION_CHANGING) && (Action != EFI_BROWSER_ACTION_CHANGED)) {
 | 
						|
    //
 | 
						|
    // All other action return unsupported.
 | 
						|
    //
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Private = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
  FakeNvData = &Private->FakeNvData;
 | 
						|
  if (!HiiGetBrowserData (&gPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData)) {
 | 
						|
    return EFI_NOT_FOUND;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Action == EFI_BROWSER_ACTION_CHANGING) {
 | 
						|
    if (Value == NULL) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
    
 | 
						|
    if (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_OFFSET + mMaxDeviceCount)) || (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_DEVICE_CLEAR) {
 | 
						|
      //
 | 
						|
      // Deletes all environment variable(s) that contain the override mappings info
 | 
						|
      //
 | 
						|
      FreeMappingDatabase (&mMappingDataBase);
 | 
						|
      Status = SaveOverridesMapping (&mMappingDataBase);
 | 
						|
      UpdateDeviceSelectPage (Private, KeyValue, FakeNvData);
 | 
						|
    }
 | 
						|
  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
 | 
						|
    if ((KeyValue >= KEY_VALUE_DRIVER_OFFSET) && (KeyValue < KEY_VALUE_DRIVER_OFFSET + mDriverImageHandleCount)) {
 | 
						|
      mDriSelection[KeyValue - KEY_VALUE_DRIVER_OFFSET] = Value->b;
 | 
						|
    } else {
 | 
						|
      switch (KeyValue) {
 | 
						|
      case KEY_VALUE_DEVICE_REFRESH:
 | 
						|
      case KEY_VALUE_DEVICE_FILTER:
 | 
						|
        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);
 | 
						|
        }
 | 
						|
      break;
 | 
						|
      
 | 
						|
      case KEY_VALUE_ORDER_SAVE_AND_EXIT:
 | 
						|
        Status = CommitChanges (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;
 | 
						|
        }
 | 
						|
      break;
 | 
						|
 | 
						|
      default:
 | 
						|
      break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Pass changed uncommitted data back to Form Browser
 | 
						|
  //
 | 
						|
  HiiSetBrowserData (&gPlatformOverridesManagerGuid, mVariableName, sizeof (PLAT_OVER_MNGR_DATA), (UINT8 *) FakeNvData, NULL);
 | 
						|
 | 
						|
  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 NULL.
 | 
						|
                                 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 function 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;
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate ConfigRouting protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiHiiConfigRoutingProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &mCallbackInfo->HiiConfigRouting
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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 (
 | 
						|
                                     &gPlatformOverridesManagerGuid,
 | 
						|
                                     mCallbackInfo->DriverHandle,
 | 
						|
                                     VfrBin,
 | 
						|
                                     PlatDriOverrideDxeStrings,
 | 
						|
                                     NULL
 | 
						|
                                     );
 | 
						|
  if (mCallbackInfo->RegisteredHandle == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto Finish;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear all the globle variable
 | 
						|
  //
 | 
						|
  mDriverImageHandleCount = 0;
 | 
						|
  mCurrentPage = 0;
 | 
						|
  
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
Finish:
 | 
						|
  PlatDriOverrideDxeUnload (ImageHandle);
 | 
						|
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT (mCallbackInfo != NULL);
 | 
						|
 | 
						|
  if (mCallbackInfo->DriverHandle != NULL) {
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           mCallbackInfo->DriverHandle,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           &mHiiVendorDevicePath,
 | 
						|
           &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
           &mCallbackInfo->ConfigAccess,
 | 
						|
           &gEfiPlatformDriverOverrideProtocolGuid,
 | 
						|
           &mCallbackInfo->PlatformDriverOverride,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  if (mCallbackInfo->RegisteredHandle != NULL) {
 | 
						|
    HiiRemovePackages (mCallbackInfo->RegisteredHandle);
 | 
						|
  }
 | 
						|
 | 
						|
  FreePool (mCallbackInfo);
 | 
						|
 | 
						|
  if (mControllerToken != NULL) {
 | 
						|
    FreePool (mControllerToken);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mControllerDevicePathProtocol != NULL) {
 | 
						|
    FreePool (mControllerDevicePathProtocol);
 | 
						|
  }
 | 
						|
 | 
						|
  if (mDriverImageToken != NULL) {
 | 
						|
    FreePool (mDriverImageToken);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |