/** @file Utility routines used by boot maintenance modules. Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
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; }