Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Gao, Liming <liming,gao@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15563 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			412 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			412 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Utility routines used by boot maintenance modules.
 | 
						|
 | 
						|
Copyright (c) 2004 - 2014, 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 "BootMaint.h"
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Function opens and returns a file handle to the root directory of a volume.
 | 
						|
 | 
						|
  @param DeviceHandle    A handle for a device
 | 
						|
 | 
						|
  @return A valid file handle or NULL is returned
 | 
						|
 | 
						|
**/
 | 
						|
EFI_FILE_HANDLE
 | 
						|
EfiLibOpenRoot (
 | 
						|
  IN EFI_HANDLE                   DeviceHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume;
 | 
						|
  EFI_FILE_HANDLE                 File;
 | 
						|
 | 
						|
  File = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // File the file system interface to the device
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  DeviceHandle,
 | 
						|
                  &gEfiSimpleFileSystemProtocolGuid,
 | 
						|
                  (VOID *) &Volume
 | 
						|
                  );
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the root directory of the volume
 | 
						|
  //
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = Volume->OpenVolume (
 | 
						|
                      Volume,
 | 
						|
                      &File
 | 
						|
                      );
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Done
 | 
						|
  //
 | 
						|
  return EFI_ERROR (Status) ? NULL : File;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Helper function called as part of the code needed
 | 
						|
  to allocate the proper sized buffer for various
 | 
						|
  EFI interfaces.
 | 
						|
 | 
						|
 | 
						|
  @param Status          Current status
 | 
						|
  @param Buffer          Current allocated buffer, or NULL
 | 
						|
  @param BufferSize      Current buffer size needed
 | 
						|
 | 
						|
  @retval  TRUE  if the buffer was reallocated and the caller
 | 
						|
                 should try the API again.
 | 
						|
  @retval  FALSE The caller should not call this function again.
 | 
						|
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
EfiGrowBuffer (
 | 
						|
  IN OUT EFI_STATUS   *Status,
 | 
						|
  IN OUT VOID         **Buffer,
 | 
						|
  IN UINTN            BufferSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  BOOLEAN TryAgain;
 | 
						|
 | 
						|
  //
 | 
						|
  // If this is an initial request, buffer will be null with a new buffer size
 | 
						|
  //
 | 
						|
  if ((*Buffer == NULL) && (BufferSize != 0)) {
 | 
						|
    *Status = EFI_BUFFER_TOO_SMALL;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If the status code is "buffer too small", resize the buffer
 | 
						|
  //
 | 
						|
  TryAgain = FALSE;
 | 
						|
  if (*Status == EFI_BUFFER_TOO_SMALL) {
 | 
						|
 | 
						|
    if (*Buffer != NULL) {
 | 
						|
      FreePool (*Buffer);
 | 
						|
    }
 | 
						|
 | 
						|
    *Buffer = AllocateZeroPool (BufferSize);
 | 
						|
 | 
						|
    if (*Buffer != NULL) {
 | 
						|
      TryAgain = TRUE;
 | 
						|
    } else {
 | 
						|
      *Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // If there's an error, free the buffer
 | 
						|
  //
 | 
						|
  if (!TryAgain && EFI_ERROR (*Status) && (*Buffer != NULL)) {
 | 
						|
    FreePool (*Buffer);
 | 
						|
    *Buffer = NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  return TryAgain;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function returns the value of the specified variable.
 | 
						|
 | 
						|
 | 
						|
  @param Name            A Null-terminated Unicode string that is
 | 
						|
                         the name of the vendor's variable.
 | 
						|
  @param VendorGuid      A unique identifier for the vendor.
 | 
						|
 | 
						|
  @return               The payload of the variable.
 | 
						|
  @retval NULL          If the variable can't be read.
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EfiLibGetVariable (
 | 
						|
  IN CHAR16               *Name,
 | 
						|
  IN EFI_GUID             *VendorGuid
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN VarSize;
 | 
						|
 | 
						|
  return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize);
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function deletes the variable specified by VarName and VarGuid.
 | 
						|
 | 
						|
  @param VarName           A Null-terminated Unicode string that is
 | 
						|
                           the name of the vendor's variable.
 | 
						|
                         
 | 
						|
  @param VarGuid           A unique identifier for the vendor.
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS           The variable was found and removed
 | 
						|
  @retval  EFI_UNSUPPORTED       The variable store was inaccessible
 | 
						|
  @retval  EFI_OUT_OF_RESOURCES  The temporary buffer was not available
 | 
						|
  @retval  EFI_NOT_FOUND         The variable was not found
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EfiLibDeleteVariable (
 | 
						|
  IN CHAR16   *VarName,
 | 
						|
  IN EFI_GUID *VarGuid
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID        *VarBuf;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  VarBuf  = EfiLibGetVariable (VarName, VarGuid);
 | 
						|
  Status  = EFI_NOT_FOUND;
 | 
						|
 | 
						|
  if (VarBuf != NULL) {
 | 
						|
    //
 | 
						|
    // Delete variable from Storage
 | 
						|
    //
 | 
						|
    Status = gRT->SetVariable (
 | 
						|
                    VarName,
 | 
						|
                    VarGuid,
 | 
						|
                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
 | 
						|
                    0,
 | 
						|
                    NULL
 | 
						|
                    );
 | 
						|
    //
 | 
						|
    // Deleting variable with current variable implementation shouldn't fail.
 | 
						|
    //
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    FreePool (VarBuf);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Function gets the file system information from an open file descriptor,
 | 
						|
  and stores it in a buffer allocated from pool.
 | 
						|
 | 
						|
 | 
						|
  @param FHand           The file handle.
 | 
						|
 | 
						|
  @return                A pointer to a buffer with file information.
 | 
						|
  @retval                NULL is returned if failed to get Vaolume Label Info.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_FILE_SYSTEM_VOLUME_LABEL *
 | 
						|
EfiLibFileSystemVolumeLabelInfo (
 | 
						|
  IN EFI_FILE_HANDLE      FHand
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  EFI_FILE_SYSTEM_VOLUME_LABEL      *Buffer;
 | 
						|
  UINTN                             BufferSize;
 | 
						|
  //
 | 
						|
  // Initialize for GrowBuffer loop
 | 
						|
  //
 | 
						|
  Buffer      = NULL;
 | 
						|
  BufferSize  = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL + 200;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call the real function
 | 
						|
  //
 | 
						|
  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
 | 
						|
    Status = FHand->GetInfo (
 | 
						|
                      FHand,
 | 
						|
                      &gEfiFileSystemVolumeLabelInfoIdGuid,
 | 
						|
                      &BufferSize,
 | 
						|
                      Buffer
 | 
						|
                      );
 | 
						|
  }
 | 
						|
 | 
						|
  return Buffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Duplicate a string.
 | 
						|
 | 
						|
  @param Src             The source.
 | 
						|
 | 
						|
  @return A new string which is duplicated copy of the source.
 | 
						|
  @retval NULL If there is not enough memory.
 | 
						|
 | 
						|
**/
 | 
						|
CHAR16 *
 | 
						|
EfiStrDuplicate (
 | 
						|
  IN CHAR16   *Src
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR16  *Dest;
 | 
						|
  UINTN   Size;
 | 
						|
 | 
						|
  Size  = StrSize (Src);
 | 
						|
  Dest  = AllocateZeroPool (Size);
 | 
						|
  ASSERT (Dest != NULL);
 | 
						|
  if (Dest != NULL) {
 | 
						|
    CopyMem (Dest, Src, Size);
 | 
						|
  }
 | 
						|
 | 
						|
  return Dest;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Function gets the file information from an open file descriptor, and stores it
 | 
						|
  in a buffer allocated from pool.
 | 
						|
 | 
						|
  @param FHand           File Handle.
 | 
						|
 | 
						|
  @return                A pointer to a buffer with file information or NULL is returned
 | 
						|
 | 
						|
**/
 | 
						|
EFI_FILE_INFO *
 | 
						|
EfiLibFileInfo (
 | 
						|
  IN EFI_FILE_HANDLE      FHand
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
  EFI_FILE_INFO *Buffer;
 | 
						|
  UINTN         BufferSize;
 | 
						|
 | 
						|
  //
 | 
						|
  // Initialize for GrowBuffer loop
 | 
						|
  //
 | 
						|
  Buffer      = NULL;
 | 
						|
  BufferSize  = SIZE_OF_EFI_FILE_INFO + 200;
 | 
						|
 | 
						|
  //
 | 
						|
  // Call the real function
 | 
						|
  //
 | 
						|
  while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
 | 
						|
    Status = FHand->GetInfo (
 | 
						|
                      FHand,
 | 
						|
                      &gEfiFileInfoGuid,
 | 
						|
                      &BufferSize,
 | 
						|
                      Buffer
 | 
						|
                      );
 | 
						|
  }
 | 
						|
 | 
						|
  return Buffer;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Function is used to determine the number of device path instances
 | 
						|
  that exist in a device path.
 | 
						|
 | 
						|
 | 
						|
  @param DevicePath      A pointer to a device path data structure.
 | 
						|
 | 
						|
  @return This function counts and returns the number of device path instances
 | 
						|
          in DevicePath.
 | 
						|
 | 
						|
**/
 | 
						|
UINTN
 | 
						|
EfiDevicePathInstanceCount (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL      *DevicePath
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Count;
 | 
						|
  UINTN Size;
 | 
						|
 | 
						|
  Count = 0;
 | 
						|
  while (GetNextDevicePathInstance (&DevicePath, &Size) != NULL) {
 | 
						|
    Count += 1;
 | 
						|
  }
 | 
						|
 | 
						|
  return Count;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Adjusts the size of a previously allocated buffer.
 | 
						|
 | 
						|
 | 
						|
  @param OldPool         - A pointer to the buffer whose size is being adjusted.
 | 
						|
  @param OldSize         - The size of the current buffer.
 | 
						|
  @param NewSize         - The size of the new buffer.
 | 
						|
 | 
						|
  @return   The newly allocated buffer.
 | 
						|
  @retval   NULL  Allocation failed.
 | 
						|
 | 
						|
**/
 | 
						|
VOID *
 | 
						|
EfiReallocatePool (
 | 
						|
  IN VOID                 *OldPool,
 | 
						|
  IN UINTN                OldSize,
 | 
						|
  IN UINTN                NewSize
 | 
						|
  )
 | 
						|
{
 | 
						|
  VOID  *NewPool;
 | 
						|
 | 
						|
  NewPool = NULL;
 | 
						|
  if (NewSize != 0) {
 | 
						|
    NewPool = AllocateZeroPool (NewSize);
 | 
						|
  }
 | 
						|
 | 
						|
  if (OldPool != NULL) {
 | 
						|
    if (NewPool != NULL) {
 | 
						|
      CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
 | 
						|
    }
 | 
						|
 | 
						|
    FreePool (OldPool);
 | 
						|
  }
 | 
						|
 | 
						|
  return NewPool;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Get a string from the Data Hub record based on 
 | 
						|
  a device path.
 | 
						|
 | 
						|
  @param DevPath         The device Path.
 | 
						|
 | 
						|
  @return A string located from the Data Hub records based on
 | 
						|
          the device path.
 | 
						|
  @retval NULL  If failed to get the String from Data Hub.
 | 
						|
 | 
						|
**/
 | 
						|
UINT16 *
 | 
						|
EfiLibStrFromDatahub (
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL                 *DevPath
 | 
						|
  )
 | 
						|
{
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 | 
						|
  Find the first instance of this Protocol
 | 
						|
  in the system and return it's interface.
 | 
						|
 | 
						|
 | 
						|
  @param ProtocolGuid    Provides the protocol to search for
 | 
						|
  @param Interface       On return, a pointer to the first interface
 | 
						|
                         that matches ProtocolGuid
 | 
						|
 | 
						|
  @retval  EFI_SUCCESS      A protocol instance matching ProtocolGuid was found
 | 
						|
  @retval  EFI_NOT_FOUND    No protocol instances were found that match ProtocolGuid
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EfiLibLocateProtocol (
 | 
						|
  IN  EFI_GUID    *ProtocolGuid,
 | 
						|
  OUT VOID        **Interface
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (
 | 
						|
                  ProtocolGuid,
 | 
						|
                  NULL,
 | 
						|
                  (VOID **) Interface
 | 
						|
                  );
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 |