Apply r5008 to this code at its new location. r5008 messsage: Fix warning on gcc by removing un-referenced static global variables. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@5034 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			1422 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1422 lines
		
	
	
		
			46 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
  PlatOverMngr.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
  A UI driver to offer a UI interface in device manager to let user configue
 | 
						|
  platform override protocol to override the default algorithm for matching
 | 
						|
  drivers to controllers.
 | 
						|
 | 
						|
  The main flow:
 | 
						|
  1. The UI driver dynamicly locate all controller device path.
 | 
						|
  2. The UI driver dynamicly locate all drivers which support binding protocol.
 | 
						|
  3. The UI driver export and dynamicly update two  menu to let user select the
 | 
						|
     mapping between drivers to controllers.
 | 
						|
  4. The UI driver save all the mapping info in NV variables which will be consumed
 | 
						|
     by platform override protocol driver to publish the platform override protocol.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PlatOverMngr.h"
 | 
						|
 | 
						|
STATIC  EFI_GUID      mPlatformOverridesManagerGuid = PLAT_OVER_MNGR_GUID;
 | 
						|
 | 
						|
STATIC  LIST_ENTRY    mMappingDataBase = INITIALIZE_LIST_HEAD_VARIABLE (mMappingDataBase);
 | 
						|
 | 
						|
STATIC  EFI_HANDLE    *mDevicePathHandleBuffer;
 | 
						|
STATIC  EFI_HANDLE    *mDriverImageHandleBuffer;
 | 
						|
 | 
						|
STATIC UINTN         mSelectedCtrIndex;
 | 
						|
STATIC EFI_STRING_ID mControllerToken[MAX_CHOICE_NUM];
 | 
						|
 | 
						|
STATIC UINTN                        mDriverImageHandleCount;
 | 
						|
STATIC EFI_STRING_ID                mDriverImageToken[MAX_CHOICE_NUM];
 | 
						|
STATIC EFI_STRING_ID                mDriverImageFilePathToken[MAX_CHOICE_NUM];
 | 
						|
STATIC EFI_LOADED_IMAGE_PROTOCOL    *mDriverImageProtocol[MAX_CHOICE_NUM];
 | 
						|
STATIC EFI_DEVICE_PATH_PROTOCOL     *mControllerDevicePathProtocol[MAX_CHOICE_NUM];
 | 
						|
STATIC UINTN                        mSelectedDriverImageNum;
 | 
						|
STATIC UINTN                        mLastSavedDriverImageNum;
 | 
						|
STATIC CHAR8                        mLanguage[RFC_3066_ENTRY_SIZE];
 | 
						|
STATIC UINT16                       mCurrentPage;
 | 
						|
 | 
						|
/**
 | 
						|
  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_HII_DATABASE_PROTOCOL   *HiiDatabase;
 | 
						|
  EFI_HII_PACKAGE_LIST_HEADER *PackageList;
 | 
						|
  EFI_CALLBACK_INFO           *CallbackInfo;
 | 
						|
  EFI_HANDLE                  DriverHandle;
 | 
						|
  EFI_FORM_BROWSER2_PROTOCOL       *FormBrowser2;
 | 
						|
 | 
						|
  //
 | 
						|
  // There should only be one HII protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiHiiDatabaseProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &HiiDatabase
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status ;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  //
 | 
						|
  // There should only be one Form Configuration protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                 &gEfiFormBrowser2ProtocolGuid,
 | 
						|
                 NULL,
 | 
						|
                 (VOID **) &FormBrowser2
 | 
						|
                 );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  CallbackInfo = AllocateZeroPool (sizeof (EFI_CALLBACK_INFO));
 | 
						|
  if (CallbackInfo == NULL) {
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE;
 | 
						|
  CallbackInfo->ConfigAccess.ExtractConfig = PlatOverMngrExtractConfig;
 | 
						|
  CallbackInfo->ConfigAccess.RouteConfig   = PlatOverMngrRouteConfig;
 | 
						|
  CallbackInfo->ConfigAccess.Callback      = PlatOverMngrCallback;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create driver handle used by HII database
 | 
						|
  //
 | 
						|
  Status = HiiLibCreateHiiDriverHandle (&DriverHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
  CallbackInfo->DriverHandle = DriverHandle;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install Config Access protocol to driver handle
 | 
						|
  //
 | 
						|
  Status = gBS->InstallProtocolInterface (
 | 
						|
                  &DriverHandle,
 | 
						|
                  &gEfiHiiConfigAccessProtocolGuid,
 | 
						|
                  EFI_NATIVE_INTERFACE,
 | 
						|
                  &CallbackInfo->ConfigAccess
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Publish our HII data
 | 
						|
  //
 | 
						|
  PackageList = HiiLibPreparePackageList (
 | 
						|
                  2,
 | 
						|
                  &mPlatformOverridesManagerGuid,
 | 
						|
                  VfrBin,
 | 
						|
                  PlatOverMngrStrings
 | 
						|
                  );
 | 
						|
  ASSERT (PackageList != NULL);
 | 
						|
 | 
						|
  Status = HiiDatabase->NewPackageList (
 | 
						|
                           HiiDatabase,
 | 
						|
                           PackageList,
 | 
						|
                           DriverHandle,
 | 
						|
                           &CallbackInfo->RegisteredHandle
 | 
						|
                           );
 | 
						|
  gBS->FreePool (PackageList);
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate ConfigRouting protocol
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiHiiConfigRoutingProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &CallbackInfo->HiiConfigRouting
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // 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,
 | 
						|
                           &CallbackInfo->RegisteredHandle,
 | 
						|
                           1,
 | 
						|
                           NULL,
 | 
						|
                           0,
 | 
						|
                           NULL,
 | 
						|
                           NULL
 | 
						|
                           );
 | 
						|
 | 
						|
  Status = HiiDatabase->RemovePackageList (HiiDatabase, CallbackInfo->RegisteredHandle);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Do some convertion for the ComponentName2 supported language. It do
 | 
						|
  the convertion just for english language code currently.
 | 
						|
 | 
						|
  @param ComponentName    Pointer to the ComponentName2 protocl pointer.
 | 
						|
  @param Language         The language string.
 | 
						|
 | 
						|
  @return   Return the duplication of Language if it is not english otherwise return
 | 
						|
            the supported english language code.
 | 
						|
 | 
						|
**/
 | 
						|
CHAR8 *
 | 
						|
ConvertComponentName2SupportLanguage (
 | 
						|
  IN EFI_COMPONENT_NAME2_PROTOCOL    *ComponentName,
 | 
						|
  IN CHAR8                           *Language
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                              *SupportedLanguages;
 | 
						|
  CHAR8                              *LangCode;
 | 
						|
  UINTN                              Index;
 | 
						|
 | 
						|
  LangCode           = NULL;
 | 
						|
  SupportedLanguages = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // treat all the english language code (en-xx or eng) equally
 | 
						|
  //
 | 
						|
  if ((AsciiStrnCmp (Language, "en-", 3) == 0) || (AsciiStrCmp (Language, "eng") == 0)) {
 | 
						|
    SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "en");
 | 
						|
    if (SupportedLanguages == NULL) {
 | 
						|
      SupportedLanguages = AsciiStrStr (ComponentName->SupportedLanguages, "eng");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // duplicate the Language if it is not english
 | 
						|
  //
 | 
						|
  if (SupportedLanguages == NULL) {
 | 
						|
    SupportedLanguages = Language;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // duplicate the returned language code.
 | 
						|
  //
 | 
						|
  if (AsciiStrStr (SupportedLanguages, "-") != NULL) {
 | 
						|
    LangCode = AllocateZeroPool(32);
 | 
						|
    for(Index = 0; (Index < 31) && (SupportedLanguages[Index] != '\0') && (SupportedLanguages[Index] != ';'); Index++) {
 | 
						|
      LangCode[Index] = SupportedLanguages[Index];
 | 
						|
    }
 | 
						|
    LangCode[Index] = '\0';
 | 
						|
  } else {
 | 
						|
    LangCode = AllocateZeroPool(4);
 | 
						|
    for(Index = 0; (Index < 3) && (SupportedLanguages[Index] != '\0'); Index++) {
 | 
						|
      LangCode[Index] = SupportedLanguages[Index];
 | 
						|
    }
 | 
						|
    LangCode[Index] = '\0';
 | 
						|
  }
 | 
						|
  return LangCode;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the 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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  EFI_COMPONENT_NAME_PROTOCOL  *ComponentName;
 | 
						|
  EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
 | 
						|
  CHAR8                        *SupportedLanguage;
 | 
						|
  CHAR16                       *DriverName;
 | 
						|
 | 
						|
  ComponentName  = NULL;
 | 
						|
  ComponentName2 = NULL;
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                 DriverBindingHandle,
 | 
						|
                 &gEfiComponentName2ProtocolGuid,
 | 
						|
                 (VOID **) &ComponentName2,
 | 
						|
                 NULL,
 | 
						|
                 NULL,
 | 
						|
                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                 );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                   DriverBindingHandle,
 | 
						|
                   &gEfiComponentNameProtocolGuid,
 | 
						|
                   (VOID **) &ComponentName,
 | 
						|
                   NULL,
 | 
						|
                   NULL,
 | 
						|
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                   );
 | 
						|
  }
 | 
						|
 | 
						|
  Status     = EFI_SUCCESS;
 | 
						|
  DriverName = NULL;
 | 
						|
  if (ComponentName != NULL) {
 | 
						|
    if (ComponentName->GetDriverName != NULL) {
 | 
						|
      Status = ComponentName->GetDriverName (
 | 
						|
                                ComponentName,
 | 
						|
                                mLanguage,
 | 
						|
                                &DriverName
 | 
						|
                                );
 | 
						|
    }
 | 
						|
  } else if (ComponentName2 != NULL) {
 | 
						|
    if (ComponentName2->GetDriverName != NULL) {
 | 
						|
      SupportedLanguage = ConvertComponentName2SupportLanguage (ComponentName2, mLanguage);
 | 
						|
      Status = ComponentName2->GetDriverName (
 | 
						|
                                 ComponentName2,
 | 
						|
                                 SupportedLanguage,
 | 
						|
                                 &DriverName
 | 
						|
                                 );
 | 
						|
        gBS->FreePool (SupportedLanguage);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return DriverName;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get the image name
 | 
						|
 | 
						|
  @param Image            Image to search.
 | 
						|
 | 
						|
  @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 *
 | 
						|
GetImageName (
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL *Image
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL          *DevPath;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL          *DevPathNode;
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  DevPath     = UnpackDevicePath (Image->FilePath);
 | 
						|
 | 
						|
  if (DevPath == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  DevPathNode = DevPath;
 | 
						|
 | 
						|
  while (!IsDevicePathEnd (DevPathNode)) {
 | 
						|
    //
 | 
						|
    // Find the Fv File path
 | 
						|
    //
 | 
						|
    NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)DevPathNode);
 | 
						|
    if (NameGuid != NULL) {
 | 
						|
      FvFilePath = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevPathNode;
 | 
						|
      Status = gBS->HandleProtocol (
 | 
						|
                    Image->DeviceHandle,
 | 
						|
                    &gEfiFirmwareVolume2ProtocolGuid,
 | 
						|
                    (VOID **) &FV2
 | 
						|
                    );
 | 
						|
      if (!EFI_ERROR (Status)) {
 | 
						|
        Status = FV2->ReadSection (
 | 
						|
                        FV2,
 | 
						|
                        &FvFilePath->FvFileName,
 | 
						|
                        EFI_SECTION_USER_INTERFACE,
 | 
						|
                        0,
 | 
						|
                        &Buffer,
 | 
						|
                        &BufferSize,
 | 
						|
                        &AuthenticationStatus
 | 
						|
                        );
 | 
						|
        if (!EFI_ERROR (Status)) {
 | 
						|
          break;
 | 
						|
        }
 | 
						|
        Buffer = NULL;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    //
 | 
						|
    // Next device path node
 | 
						|
    //
 | 
						|
    DevPathNode = NextDevicePathNode (DevPathNode);
 | 
						|
  }
 | 
						|
 | 
						|
    gBS->FreePool (DevPath);
 | 
						|
  return Buffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Prepare the first page to let user select the device controller which need to
 | 
						|
  add mapping 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_HII_UPDATE_DATA                       UpdateData;
 | 
						|
  EFI_STATUS                                Status;
 | 
						|
  UINTN                                     LangSize;
 | 
						|
  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;
 | 
						|
 | 
						|
  mCurrentPage = FORM_ID_DEVICE;
 | 
						|
  //
 | 
						|
  // Following code will be run 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
 | 
						|
  //
 | 
						|
 | 
						|
  LangSize = RFC_3066_ENTRY_SIZE;
 | 
						|
  Status = gRT->GetVariable (
 | 
						|
              L"PlatformLang",
 | 
						|
              &gEfiGlobalVariableGuid,
 | 
						|
              NULL,
 | 
						|
              &LangSize,
 | 
						|
              mLanguage
 | 
						|
              );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Initial the mapping database in memory
 | 
						|
  //
 | 
						|
  FreeMappingDatabase (&mMappingDataBase);
 | 
						|
  Status = InitOverridesMapping (&mMappingDataBase);
 | 
						|
 | 
						|
  //
 | 
						|
  // Clear all the content in the first page
 | 
						|
  //
 | 
						|
  UpdateData.BufferSize = UPDATE_DATA_SIZE;
 | 
						|
  UpdateData.Offset = 0;
 | 
						|
  UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
 | 
						|
  ASSERT (UpdateData.Data != NULL);
 | 
						|
  //
 | 
						|
  // Clear first page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_DEVICE,
 | 
						|
    FORM_ID_DEVICE,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // 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);
 | 
						|
  HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH), &NewString);
 | 
						|
  ASSERT (NewString != NULL);
 | 
						|
  Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  gBS->FreePool (NewString);
 | 
						|
 | 
						|
  NewStringToken = STRING_TOKEN (STR_FIRST_REFRESH_HELP);
 | 
						|
  HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_REFRESH_HELP), &NewString);
 | 
						|
  ASSERT (NewString != NULL);
 | 
						|
  Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  gBS->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"--"));
 | 
						|
    if (EFI_ERROR (CheckMapping (ControllerDevicePath,NULL, &mMappingDataBase, NULL, NULL))) {
 | 
						|
      StrCat (NewString, L"--");
 | 
						|
    } else {
 | 
						|
      StrCat (NewString, L"**");
 | 
						|
    }
 | 
						|
    StrCat (NewString, ControllerName);
 | 
						|
 | 
						|
    NewStringToken = mControllerToken[Index];
 | 
						|
    if (NewStringToken == 0) {
 | 
						|
      Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);
 | 
						|
    } else {
 | 
						|
      Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
 | 
						|
    }
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    gBS->FreePool (NewString);
 | 
						|
    //
 | 
						|
    // Save the device path string toke for next access use
 | 
						|
    //
 | 
						|
    mControllerToken[Index] = NewStringToken;
 | 
						|
 | 
						|
    CreateGotoOpCode (
 | 
						|
      FORM_ID_DRIVER,
 | 
						|
      NewStringToken,
 | 
						|
      STRING_TOKEN (STR_GOTO_HELP_DRIVER),
 | 
						|
      EFI_IFR_FLAG_CALLBACK,
 | 
						|
      (UINT16) (Index + KEY_VALUE_DEVICE_OFFSET),
 | 
						|
      &UpdateData
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update first page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_DEVICE,
 | 
						|
    FORM_ID_DEVICE,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  gBS->FreePool (UpdateData.Data);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  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.
 | 
						|
  @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_HII_UPDATE_DATA                       UpdateData;
 | 
						|
  EFI_STATUS                                Status;
 | 
						|
  UINTN                                     Index;
 | 
						|
 | 
						|
  CHAR16                                    *NewString;
 | 
						|
  EFI_STRING_ID                             NewStringToken;
 | 
						|
  EFI_STRING_ID                             NewStringHelpToken;
 | 
						|
  UINTN                                     DriverImageHandleCount;
 | 
						|
 | 
						|
  EFI_DRIVER_BINDING_PROTOCOL               *DriverBindingInterface;
 | 
						|
  EFI_LOADED_IMAGE_PROTOCOL                 *LoadedImage;
 | 
						|
  CHAR16                                    *DriverName;
 | 
						|
  BOOLEAN                                   FreeDriverName;
 | 
						|
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL                  *LoadedImageDevicePath;
 | 
						|
  EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride;
 | 
						|
  EFI_HANDLE                                DriverBindingHandle;
 | 
						|
  //
 | 
						|
  // 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 - 0x100;
 | 
						|
  ASSERT (mSelectedCtrIndex < MAX_CHOICE_NUM);
 | 
						|
  mLastSavedDriverImageNum = 0;
 | 
						|
  //
 | 
						|
  // Clear all the content in dynamic page
 | 
						|
  //
 | 
						|
  UpdateData.BufferSize = UPDATE_DATA_SIZE;
 | 
						|
  UpdateData.Offset = 0;
 | 
						|
  UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
 | 
						|
  ASSERT (UpdateData.Data != NULL);
 | 
						|
  //
 | 
						|
  // Clear second page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_DRIVER,
 | 
						|
    FORM_ID_DRIVER,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // 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
 | 
						|
    //
 | 
						|
    DriverBindingInterface = NULL;
 | 
						|
    DriverBindingHandle = NULL;
 | 
						|
    DriverBindingInterface = GetBindingProtocolFromImageHandle (
 | 
						|
                                mDriverImageHandleBuffer[Index],
 | 
						|
                                &DriverBindingHandle
 | 
						|
                                );
 | 
						|
    if (DriverBindingInterface == 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
 | 
						|
      //
 | 
						|
      HiiLibGetStringFromHandle (Private->RegisteredHandle, STRING_TOKEN (STR_DRIVER_DEFAULT_NAME), &DriverName);
 | 
						|
      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));
 | 
						|
    if (EFI_ERROR (CheckMapping (mControllerDevicePathProtocol[mSelectedCtrIndex], LoadedImageDevicePath, &mMappingDataBase, NULL, NULL))) {
 | 
						|
      FakeNvData->DriSelection[Index] = 0x00;
 | 
						|
    } else {
 | 
						|
      FakeNvData->DriSelection[Index] = 0x01;
 | 
						|
      mLastSavedDriverImageNum++;
 | 
						|
    }
 | 
						|
    StrCat (NewString, DriverName);
 | 
						|
    NewStringToken = mDriverImageToken[Index];
 | 
						|
    if (NewStringToken == 0) {
 | 
						|
      Status = HiiLibNewString (Private->RegisteredHandle, &NewStringToken, NewString);
 | 
						|
    } else {
 | 
						|
      Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, NewString);
 | 
						|
    }
 | 
						|
    mDriverImageToken[Index] = NewStringToken;
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    gBS->FreePool (NewString);
 | 
						|
    if (FreeDriverName) {
 | 
						|
      gBS->FreePool (DriverName);
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Second create the driver image device path as item help string
 | 
						|
    //
 | 
						|
    DriverName = DevicePathToStr (LoadedImageDevicePath);
 | 
						|
 | 
						|
    NewString = AllocateZeroPool (StrSize (DriverName));
 | 
						|
    StrCat (NewString, DriverName);
 | 
						|
    NewStringHelpToken = mDriverImageFilePathToken[Index];
 | 
						|
    if (NewStringHelpToken == 0) {
 | 
						|
      Status = HiiLibNewString (Private->RegisteredHandle, &NewStringHelpToken, NewString);
 | 
						|
    } else {
 | 
						|
      Status = HiiLibSetString (Private->RegisteredHandle, NewStringHelpToken, NewString);
 | 
						|
    }
 | 
						|
    mDriverImageFilePathToken[Index] = NewStringHelpToken;
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    gBS->FreePool (NewString);
 | 
						|
    gBS->FreePool (DriverName);
 | 
						|
 | 
						|
    CreateCheckBoxOpCode (
 | 
						|
      (UINT16) (DRIVER_SELECTION_QUESTION_ID + Index),
 | 
						|
      VARSTORE_ID_PLAT_OVER_MNGR,
 | 
						|
      (UINT16) (DRIVER_SELECTION_VAR_OFFSET + Index),
 | 
						|
      NewStringToken,
 | 
						|
      NewStringHelpToken,
 | 
						|
      0,
 | 
						|
      0,
 | 
						|
      &UpdateData
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update second page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_DRIVER,
 | 
						|
    FORM_ID_DRIVER,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  gBS->FreePool (UpdateData.Data);
 | 
						|
  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
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HII_UPDATE_DATA                       UpdateData;
 | 
						|
  UINTN                                     Index;
 | 
						|
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL                  *LoadedImageDevicePath;
 | 
						|
 | 
						|
  IFR_OPTION                                *IfrOptionList;
 | 
						|
  UINTN                                     SelectedDriverImageNum;
 | 
						|
  UINT32                                    DriverImageNO;
 | 
						|
  UINTN                                     MinNO;
 | 
						|
  UINTN                                     Index1;
 | 
						|
  UINTN                                     TempNO[100];
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
 | 
						|
  UpdateData.BufferSize = UPDATE_DATA_SIZE;
 | 
						|
  UpdateData.Offset = 0;
 | 
						|
  UpdateData.Data = AllocateZeroPool (UPDATE_DATA_SIZE);
 | 
						|
  ASSERT (UpdateData.Data != NULL);
 | 
						|
  //
 | 
						|
  // Clear third page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_ORDER,
 | 
						|
    FORM_ID_ORDER,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // 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;
 | 
						|
  }
 | 
						|
 | 
						|
  IfrOptionList = AllocateZeroPool (0x200);
 | 
						|
  ASSERT_EFI_ERROR (IfrOptionList != NULL);
 | 
						|
  //
 | 
						|
  // Create order list for those selected drivers
 | 
						|
  //
 | 
						|
  SelectedDriverImageNum = 0;
 | 
						|
  for (Index = 0; Index < mDriverImageHandleCount; Index++) {
 | 
						|
    if (FakeNvData->DriSelection[Index] != 0) {
 | 
						|
      IfrOptionList[SelectedDriverImageNum].StringToken = mDriverImageToken[Index];
 | 
						|
      //
 | 
						|
      // Use the NO. in driver binding buffer as value, will use it later
 | 
						|
      //
 | 
						|
      IfrOptionList[SelectedDriverImageNum].Value.u8 = (UINT8) (Index + 1);
 | 
						|
      IfrOptionList[SelectedDriverImageNum].Flags = 0;
 | 
						|
 | 
						|
      //
 | 
						|
      // 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;
 | 
						|
      SelectedDriverImageNum ++;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  ASSERT (SelectedDriverImageNum == mSelectedDriverImageNum);
 | 
						|
  //
 | 
						|
  // NvRamMap Must be clear firstly
 | 
						|
  //
 | 
						|
  ZeroMem (FakeNvData->DriOrder, 100);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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] =IfrOptionList[MinNO].Value.u8;
 | 
						|
    TempNO[MinNO] = 101;
 | 
						|
  }
 | 
						|
 | 
						|
  CreateOrderedListOpCode (
 | 
						|
    (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,
 | 
						|
    100,
 | 
						|
    IfrOptionList,
 | 
						|
    SelectedDriverImageNum,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Update third page form
 | 
						|
  //
 | 
						|
  IfrLibUpdateForm (
 | 
						|
    Private->RegisteredHandle,
 | 
						|
    &mPlatformOverridesManagerGuid,
 | 
						|
    FORM_ID_ORDER,
 | 
						|
    FORM_ID_ORDER,
 | 
						|
    FALSE,
 | 
						|
    &UpdateData
 | 
						|
    );
 | 
						|
 | 
						|
  gBS->FreePool (IfrOptionList);
 | 
						|
  gBS->FreePool (UpdateData.Data);
 | 
						|
  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 <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 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;
 | 
						|
 | 
						|
  Private = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
  HiiConfigRouting = Private->HiiConfigRouting;
 | 
						|
 | 
						|
  //
 | 
						|
  // Convert buffer data to <ConfigResp> 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  Request      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;
 | 
						|
  EFI_STATUS                                Status;
 | 
						|
  UINT16                                    KeyValue;
 | 
						|
  UINTN                                     BufferSize;
 | 
						|
  PLAT_OVER_MNGR_DATA                       *FakeNvData;
 | 
						|
 | 
						|
  Private     = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
 | 
						|
  FakeNvData = &Private->FakeNvData;
 | 
						|
  BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
 | 
						|
  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  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);
 | 
						|
  }
 | 
						|
  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 <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;
 | 
						|
  UINTN                                     BufferSize;
 | 
						|
  PLAT_OVER_MNGR_DATA                       *FakeNvData;
 | 
						|
  EFI_INPUT_KEY                             Key;
 | 
						|
 | 
						|
  Private = EFI_CALLBACK_INFO_FROM_THIS (This);
 | 
						|
 | 
						|
  FakeNvData = &Private->FakeNvData;
 | 
						|
  BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
 | 
						|
  Status = GetBrowserData (NULL, NULL, &BufferSize, (UINT8 *) FakeNvData);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  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);
 | 
						|
    Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"First, Select the controller by device path");
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (((KEY_VALUE_DEVICE_OFFSET <= KeyValue) && (KeyValue < KEY_VALUE_DEVICE_MAX)) || (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS)) {
 | 
						|
    if (KeyValue == KEY_VALUE_ORDER_GOTO_PREVIOUS) {
 | 
						|
      KeyValue = (EFI_QUESTION_ID) (mSelectedCtrIndex + 0x100);
 | 
						|
    }
 | 
						|
    UpdateBindingDriverSelectPage (Private, KeyValue, FakeNvData);
 | 
						|
    //
 | 
						|
    // Update page title string
 | 
						|
    //
 | 
						|
    NewStringToken = STRING_TOKEN (STR_TITLE);
 | 
						|
    Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Second, Select drivers for the previous selected controller");
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (KeyValue == KEY_VALUE_DRIVER_GOTO_ORDER) {
 | 
						|
    UpdatePrioritySelectPage (Private, KeyValue, FakeNvData);
 | 
						|
    //
 | 
						|
    // Update page title string
 | 
						|
    //
 | 
						|
    NewStringToken = STRING_TOKEN (STR_TITLE);
 | 
						|
    Status = HiiLibSetString (Private->RegisteredHandle, NewStringToken, L"Finally, Set the priority order for the drivers and save them");
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
  }
 | 
						|
 | 
						|
  if (KeyValue == KEY_VALUE_ORDER_SAVE_AND_EXIT) {
 | 
						|
    Status = CommintChanges (Private, KeyValue, FakeNvData);
 | 
						|
    *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT;
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      IfrLibCreatePopUp (1, &Key, L"Single Override Info too large, Saving Error!");
 | 
						|
      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
 | 
						|
  //
 | 
						|
  BufferSize = sizeof (PLAT_OVER_MNGR_DATA);
 | 
						|
  Status = SetBrowserData (NULL, NULL, BufferSize, (UINT8 *) FakeNvData, NULL);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function unpacks a device path data structure so that all the nodes
 | 
						|
  of a device path are naturally aligned.
 | 
						|
 | 
						|
  @param  DevPath  A pointer to a device path data structure
 | 
						|
 | 
						|
  @return If the memory for the device path is successfully allocated, then a
 | 
						|
  @return pointer to the new device path is returned.  Otherwise, NULL is returned.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_DEVICE_PATH_PROTOCOL *
 | 
						|
UnpackDevicePath (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL  *DevPath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Src;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *Dest;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *NewPath;
 | 
						|
  UINTN                     Size;
 | 
						|
 | 
						|
  //
 | 
						|
  // Walk device path and round sizes to valid boundries
 | 
						|
  //
 | 
						|
  Src   = DevPath;
 | 
						|
  Size  = 0;
 | 
						|
  for (;;) {
 | 
						|
    Size += DevicePathNodeLength (Src);
 | 
						|
    Size += ALIGN_SIZE (Size);
 | 
						|
 | 
						|
    if (IsDevicePathEnd (Src)) {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
    Src = NextDevicePathNode (Src);
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Allocate space for the unpacked path
 | 
						|
  //
 | 
						|
  NewPath = AllocateZeroPool (Size);
 | 
						|
  if (NewPath) {
 | 
						|
 | 
						|
    ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0);
 | 
						|
 | 
						|
    //
 | 
						|
    // Copy each node
 | 
						|
    //
 | 
						|
    Src   = DevPath;
 | 
						|
    Dest  = NewPath;
 | 
						|
    for (;;) {
 | 
						|
      Size = DevicePathNodeLength (Src);
 | 
						|
      CopyMem (Dest, Src, Size);
 | 
						|
      Size += ALIGN_SIZE (Size);
 | 
						|
      SetDevicePathNodeLength (Dest, Size);
 | 
						|
      Dest->Type |= EFI_DP_TYPE_UNPACKED;
 | 
						|
      Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size);
 | 
						|
 | 
						|
      if (IsDevicePathEnd (Src)) {
 | 
						|
        break;
 | 
						|
      }
 | 
						|
 | 
						|
      Src = NextDevicePathNode (Src);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NewPath;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Get the description string by device path.
 | 
						|
 | 
						|
  @param  DevPath     The input device path.
 | 
						|
 | 
						|
  @retval !NULL       The description string retured.
 | 
						|
  @retval  NULL       The description string cannot be found.
 | 
						|
 | 
						|
**/
 | 
						|
CHAR16 *
 | 
						|
DevicePathToStr (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                       Status;
 | 
						|
  CHAR16                           *ToText;
 | 
						|
  EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText;
 | 
						|
 | 
						|
  if (DevPath == NULL) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  &gEfiDevicePathToTextProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) &DevPathToText
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    ToText = DevPathToText->ConvertDevicePathToText (
 | 
						|
                              DevPath,
 | 
						|
                              FALSE,
 | 
						|
                              TRUE
 | 
						|
                              );
 | 
						|
    ASSERT (ToText != NULL);
 | 
						|
    return ToText;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 |