audk/IntelFrameworkModulePkg/Universal/BdsDxe/BootMaint/BmLib.c

370 lines
8.4 KiB
C
Raw Normal View History

/** @file
Utility routines used by boot maintenance modules.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#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;
}
/**
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;
}