REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the OvmfPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Andrew Fish <afish@apple.com>
		
			
				
	
	
		
			642 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			642 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  EFI_FILE_PROTOCOL.SetInfo() member function for the Virtio Filesystem driver.
 | 
						|
 | 
						|
  Copyright (C) 2020, Red Hat, Inc.
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Guid/FileSystemInfo.h>            // gEfiFileSystemInfoGuid
 | 
						|
#include <Guid/FileSystemVolumeLabelInfo.h> // gEfiFileSystemVolumeLabelInfo...
 | 
						|
#include <Library/BaseLib.h>                // StrCmp()
 | 
						|
#include <Library/BaseMemoryLib.h>          // CompareGuid()
 | 
						|
#include <Library/MemoryAllocationLib.h>    // FreePool()
 | 
						|
 | 
						|
#include "VirtioFsDxe.h"
 | 
						|
 | 
						|
/**
 | 
						|
  Validate a buffer that the EFI_FILE_PROTOCOL.SetInfo() caller passes in for a
 | 
						|
  particular InformationType GUID.
 | 
						|
 | 
						|
  The structure to be validated is supposed to end with a variable-length,
 | 
						|
  NUL-terminated CHAR16 Name string.
 | 
						|
 | 
						|
  @param[in] SizeByProtocolCaller  The BufferSize parameter as provided by the
 | 
						|
                                   EFI_FILE_PROTOCOL.SetInfo() caller.
 | 
						|
 | 
						|
  @param[in] MinimumStructSize     The minimum structure size that is required
 | 
						|
                                   for the given InformationType GUID,
 | 
						|
                                   including a single CHAR16 element from the
 | 
						|
                                   trailing Name field.
 | 
						|
 | 
						|
  @param[in] IsSizeByInfoPresent   TRUE if and only if the expected structure
 | 
						|
                                   starts with a UINT64 Size field that reports
 | 
						|
                                   the actual structure size.
 | 
						|
 | 
						|
  @param[in] Buffer                The Buffer parameter as provided by the
 | 
						|
                                   EFI_FILE_PROTOCOL.SetInfo() caller.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS            Validation successful, Buffer is well-formed.
 | 
						|
 | 
						|
  @retval EFI_BAD_BUFFER_SIZE    The EFI_FILE_PROTOCOL.SetInfo()
 | 
						|
                                 caller provided a BufferSize that is smaller
 | 
						|
                                 than the minimum structure size required for
 | 
						|
                                 the given InformationType GUID.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  IsSizeByInfoPresent is TRUE, and the leading
 | 
						|
                                 UINT64 Size field does not match the
 | 
						|
                                 EFI_FILE_PROTOCOL.SetInfo() caller-provided
 | 
						|
                                 BufferSize.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  The trailing Name field does not consist of a
 | 
						|
                                 whole multiple of CHAR16 elements.
 | 
						|
 | 
						|
  @retval EFI_INVALID_PARAMETER  The trailing Name field is not NUL-terminated.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
ValidateInfoStructure (
 | 
						|
  IN UINTN    SizeByProtocolCaller,
 | 
						|
  IN UINTN    MinimumStructSize,
 | 
						|
  IN BOOLEAN  IsSizeByInfoPresent,
 | 
						|
  IN VOID     *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN   NameFieldByteOffset;
 | 
						|
  UINTN   NameFieldBytes;
 | 
						|
  UINTN   NameFieldChar16s;
 | 
						|
  CHAR16  *NameField;
 | 
						|
 | 
						|
  //
 | 
						|
  // Make sure the internal function asking for validation passes in sane
 | 
						|
  // values.
 | 
						|
  //
 | 
						|
  ASSERT (MinimumStructSize >= sizeof (CHAR16));
 | 
						|
  NameFieldByteOffset = MinimumStructSize - sizeof (CHAR16);
 | 
						|
 | 
						|
  if (IsSizeByInfoPresent) {
 | 
						|
    ASSERT (MinimumStructSize >= sizeof (UINT64) + sizeof (CHAR16));
 | 
						|
    ASSERT (NameFieldByteOffset >= sizeof (UINT64));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the protocol caller provided enough bytes for the minimum
 | 
						|
  // size of this info structure.
 | 
						|
  //
 | 
						|
  if (SizeByProtocolCaller < MinimumStructSize) {
 | 
						|
    return EFI_BAD_BUFFER_SIZE;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the info structure starts with a UINT64 Size field, check if that
 | 
						|
  // agrees with the protocol caller-provided size.
 | 
						|
  //
 | 
						|
  if (IsSizeByInfoPresent) {
 | 
						|
    UINT64  *SizeByInfo;
 | 
						|
 | 
						|
    SizeByInfo = Buffer;
 | 
						|
    if (*SizeByInfo != SizeByProtocolCaller) {
 | 
						|
      return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The CHAR16 Name field at the end of the structure must have an even number
 | 
						|
  // of bytes.
 | 
						|
  //
 | 
						|
  // The subtraction below cannot underflow, and yields at least
 | 
						|
  // sizeof(CHAR16).
 | 
						|
  //
 | 
						|
  ASSERT (SizeByProtocolCaller >= NameFieldByteOffset);
 | 
						|
  NameFieldBytes = SizeByProtocolCaller - NameFieldByteOffset;
 | 
						|
  ASSERT (NameFieldBytes >= sizeof (CHAR16));
 | 
						|
  if (NameFieldBytes % sizeof (CHAR16) != 0) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // The CHAR16 Name field at the end of the structure must be NUL-terminated.
 | 
						|
  //
 | 
						|
  NameFieldChar16s = NameFieldBytes / sizeof (CHAR16);
 | 
						|
  ASSERT (NameFieldChar16s >= 1);
 | 
						|
 | 
						|
  NameField = (CHAR16 *)((UINT8 *)Buffer + NameFieldByteOffset);
 | 
						|
  if (NameField[NameFieldChar16s - 1] != L'\0') {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Rename a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.FileName.
 | 
						|
 | 
						|
  @param[in,out] VirtioFsFile  The VIRTIO_FS_FILE to rename.
 | 
						|
 | 
						|
  @param[in] NewFileName       The new file name requested by
 | 
						|
                               EFI_FILE_PROTOCOL.SetInfo().
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        The canonical format destination path that is
 | 
						|
                             determined from the input value of
 | 
						|
                             VirtioFsFile->CanonicalPathname and from
 | 
						|
                             NewFileName is identical to the input value of
 | 
						|
                             VirtioFsFile->CanonicalPathname. This means that
 | 
						|
                             EFI_FILE_INFO does not constitute a rename
 | 
						|
                             request. VirtioFsFile has not been changed.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        VirtioFsFile has been renamed.
 | 
						|
                             VirtioFsFile->CanonicalPathname has assumed the
 | 
						|
                             destination pathname in canonical format.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED  VirtioFsFile refers to the root directory, and
 | 
						|
                             NewFileName expresses an actual rename/move
 | 
						|
                             request.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED  VirtioFsFile is the (possibly indirect) parent
 | 
						|
                             directory of at least one other VIRTIO_FS_FILE
 | 
						|
                             that is open for the same Virtio Filesystem
 | 
						|
                             (identified by VirtioFsFile->OwnerFs). Renaming
 | 
						|
                             VirtioFsFile would invalidate the canonical
 | 
						|
                             pathnames of those VIRTIO_FS_FILE instances;
 | 
						|
                             therefore the request has been rejected.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED  VirtioFsFile is not open for writing, but
 | 
						|
                             NewFileName expresses an actual rename/move
 | 
						|
                             request.
 | 
						|
 | 
						|
  @retval EFI_NOT_FOUND      At least one dot-dot component in NewFileName
 | 
						|
                             attempted to escape the root directory.
 | 
						|
 | 
						|
  @return                    Error codes propagated from underlying functions.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
Rename (
 | 
						|
  IN OUT VIRTIO_FS_FILE  *VirtioFsFile,
 | 
						|
  IN     CHAR16          *NewFileName
 | 
						|
  )
 | 
						|
{
 | 
						|
  VIRTIO_FS   *VirtioFs;
 | 
						|
  EFI_STATUS  Status;
 | 
						|
  CHAR8       *Destination;
 | 
						|
  BOOLEAN     RootEscape;
 | 
						|
  UINT64      OldParentDirNodeId;
 | 
						|
  CHAR8       *OldLastComponent;
 | 
						|
  UINT64      NewParentDirNodeId;
 | 
						|
  CHAR8       *NewLastComponent;
 | 
						|
 | 
						|
  VirtioFs = VirtioFsFile->OwnerFs;
 | 
						|
 | 
						|
  //
 | 
						|
  // The root directory cannot be renamed.
 | 
						|
  //
 | 
						|
  if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, "/") == 0) {
 | 
						|
    if (StrCmp (NewFileName, L"") == 0) {
 | 
						|
      //
 | 
						|
      // Not a rename request anyway.
 | 
						|
      //
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_ACCESS_DENIED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Compose the canonical pathname for the destination.
 | 
						|
  //
 | 
						|
  Status = VirtioFsComposeRenameDestination (
 | 
						|
             VirtioFsFile->CanonicalPathname,
 | 
						|
             NewFileName,
 | 
						|
             &Destination,
 | 
						|
             &RootEscape
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  if (RootEscape) {
 | 
						|
    Status = EFI_NOT_FOUND;
 | 
						|
    goto FreeDestination;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the rename would leave VirtioFsFile->CanonicalPathname unchanged, then
 | 
						|
  // EFI_FILE_PROTOCOL.SetInfo() isn't asking for a rename actually.
 | 
						|
  //
 | 
						|
  if (AsciiStrCmp (VirtioFsFile->CanonicalPathname, Destination) == 0) {
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
    goto FreeDestination;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if the rename would break the canonical pathnames of other
 | 
						|
  // VIRTIO_FS_FILE instances of the same VIRTIO_FS.
 | 
						|
  //
 | 
						|
  if (VirtioFsFile->IsDirectory) {
 | 
						|
    UINTN       PathLen;
 | 
						|
    LIST_ENTRY  *OpenFilesEntry;
 | 
						|
 | 
						|
    PathLen = AsciiStrLen (VirtioFsFile->CanonicalPathname);
 | 
						|
    BASE_LIST_FOR_EACH (OpenFilesEntry, &VirtioFs->OpenFiles) {
 | 
						|
      VIRTIO_FS_FILE  *OtherFile;
 | 
						|
 | 
						|
      OtherFile = VIRTIO_FS_FILE_FROM_OPEN_FILES_ENTRY (OpenFilesEntry);
 | 
						|
      if ((OtherFile != VirtioFsFile) &&
 | 
						|
          (AsciiStrnCmp (
 | 
						|
             VirtioFsFile->CanonicalPathname,
 | 
						|
             OtherFile->CanonicalPathname,
 | 
						|
             PathLen
 | 
						|
             ) == 0) &&
 | 
						|
          ((OtherFile->CanonicalPathname[PathLen] == '\0') ||
 | 
						|
           (OtherFile->CanonicalPathname[PathLen] == '/')))
 | 
						|
      {
 | 
						|
        //
 | 
						|
        // OtherFile refers to the same directory as VirtioFsFile, or is a
 | 
						|
        // (possibly indirect) child of the directory referred to by
 | 
						|
        // VirtioFsFile.
 | 
						|
        //
 | 
						|
        Status = EFI_ACCESS_DENIED;
 | 
						|
        goto FreeDestination;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // From this point on, the file needs to be open for writing.
 | 
						|
  //
 | 
						|
  if (!VirtioFsFile->IsOpenForWriting) {
 | 
						|
    Status = EFI_ACCESS_DENIED;
 | 
						|
    goto FreeDestination;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Split both source and destination canonical pathnames into (most specific
 | 
						|
  // parent directory, last component) pairs.
 | 
						|
  //
 | 
						|
  Status = VirtioFsLookupMostSpecificParentDir (
 | 
						|
             VirtioFs,
 | 
						|
             VirtioFsFile->CanonicalPathname,
 | 
						|
             &OldParentDirNodeId,
 | 
						|
             &OldLastComponent
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto FreeDestination;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = VirtioFsLookupMostSpecificParentDir (
 | 
						|
             VirtioFs,
 | 
						|
             Destination,
 | 
						|
             &NewParentDirNodeId,
 | 
						|
             &NewLastComponent
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ForgetOldParentDirNodeId;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Perform the rename. If the destination path exists, the rename will fail.
 | 
						|
  //
 | 
						|
  Status = VirtioFsFuseRename (
 | 
						|
             VirtioFs,
 | 
						|
             OldParentDirNodeId,
 | 
						|
             OldLastComponent,
 | 
						|
             NewParentDirNodeId,
 | 
						|
             NewLastComponent
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ForgetNewParentDirNodeId;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Swap in the new canonical pathname.
 | 
						|
  //
 | 
						|
  FreePool (VirtioFsFile->CanonicalPathname);
 | 
						|
  VirtioFsFile->CanonicalPathname = Destination;
 | 
						|
  Destination                     = NULL;
 | 
						|
  Status                          = EFI_SUCCESS;
 | 
						|
 | 
						|
  //
 | 
						|
  // Fall through.
 | 
						|
  //
 | 
						|
ForgetNewParentDirNodeId:
 | 
						|
  if (NewParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
 | 
						|
    VirtioFsFuseForget (VirtioFs, NewParentDirNodeId);
 | 
						|
  }
 | 
						|
 | 
						|
ForgetOldParentDirNodeId:
 | 
						|
  if (OldParentDirNodeId != VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID) {
 | 
						|
    VirtioFsFuseForget (VirtioFs, OldParentDirNodeId);
 | 
						|
  }
 | 
						|
 | 
						|
FreeDestination:
 | 
						|
  if (Destination != NULL) {
 | 
						|
    FreePool (Destination);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Update the attributes of a VIRTIO_FS_FILE as requested in EFI_FILE_INFO.
 | 
						|
 | 
						|
  @param[in,out] VirtioFsFile  The VIRTIO_FS_FILE to update the attributes of.
 | 
						|
 | 
						|
  @param[in] NewFileInfo       The new attributes requested by
 | 
						|
                               EFI_FILE_PROTOCOL.SetInfo(). NewFileInfo->Size
 | 
						|
                               and NewFileInfo->FileName are ignored.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        No attributes had to be updated.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        The required set of attribute updates has been
 | 
						|
                             determined and performed successfully.
 | 
						|
 | 
						|
  @retval EFI_ACCESS_DENIED  NewFileInfo requests an update to a property
 | 
						|
                             different from the EFI_FILE_READ_ONLY bit in the
 | 
						|
                             Attribute field, but VirtioFsFile is not open for
 | 
						|
                             writing.
 | 
						|
 | 
						|
  @return                    Error codes propagated from underlying functions.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
UpdateAttributes (
 | 
						|
  IN OUT VIRTIO_FS_FILE  *VirtioFsFile,
 | 
						|
  IN     EFI_FILE_INFO   *NewFileInfo
 | 
						|
  )
 | 
						|
{
 | 
						|
  VIRTIO_FS                           *VirtioFs;
 | 
						|
  EFI_STATUS                          Status;
 | 
						|
  VIRTIO_FS_FUSE_ATTRIBUTES_RESPONSE  FuseAttr;
 | 
						|
  EFI_FILE_INFO                       FileInfo;
 | 
						|
  BOOLEAN                             UpdateFileSize;
 | 
						|
  UINT64                              FileSize;
 | 
						|
  BOOLEAN                             UpdateAtime;
 | 
						|
  BOOLEAN                             UpdateMtime;
 | 
						|
  UINT64                              Atime;
 | 
						|
  UINT64                              Mtime;
 | 
						|
  BOOLEAN                             UpdateMode;
 | 
						|
  UINT32                              Mode;
 | 
						|
 | 
						|
  VirtioFs = VirtioFsFile->OwnerFs;
 | 
						|
 | 
						|
  //
 | 
						|
  // Fetch the current attributes first, so we can build the difference between
 | 
						|
  // them and NewFileInfo.
 | 
						|
  //
 | 
						|
  Status = VirtioFsFuseGetAttr (VirtioFs, VirtioFsFile->NodeId, &FuseAttr);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = VirtioFsFuseAttrToEfiFileInfo (&FuseAttr, &FileInfo);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Collect the updates.
 | 
						|
  //
 | 
						|
  if (VirtioFsFile->IsDirectory) {
 | 
						|
    UpdateFileSize = FALSE;
 | 
						|
  } else {
 | 
						|
    VirtioFsGetFuseSizeUpdate (
 | 
						|
      &FileInfo,
 | 
						|
      NewFileInfo,
 | 
						|
      &UpdateFileSize,
 | 
						|
      &FileSize
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  Status = VirtioFsGetFuseTimeUpdates (
 | 
						|
             &FileInfo,
 | 
						|
             NewFileInfo,
 | 
						|
             &UpdateAtime,
 | 
						|
             &UpdateMtime,
 | 
						|
             &Atime,
 | 
						|
             &Mtime
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = VirtioFsGetFuseModeUpdate (
 | 
						|
             &FileInfo,
 | 
						|
             NewFileInfo,
 | 
						|
             &UpdateMode,
 | 
						|
             &Mode
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If no attribute updates are necessary, we're done.
 | 
						|
  //
 | 
						|
  if (!UpdateFileSize && !UpdateAtime && !UpdateMtime && !UpdateMode) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // If the file is not open for writing, then only Mode may be updated (for
 | 
						|
  // toggling EFI_FILE_READ_ONLY).
 | 
						|
  //
 | 
						|
  if (!VirtioFsFile->IsOpenForWriting &&
 | 
						|
      (UpdateFileSize || UpdateAtime || UpdateMtime))
 | 
						|
  {
 | 
						|
    return EFI_ACCESS_DENIED;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Send the FUSE_SETATTR request now.
 | 
						|
  //
 | 
						|
  Status = VirtioFsFuseSetAttr (
 | 
						|
             VirtioFs,
 | 
						|
             VirtioFsFile->NodeId,
 | 
						|
             UpdateFileSize ? &FileSize : NULL,
 | 
						|
             UpdateAtime    ? &Atime    : NULL,
 | 
						|
             UpdateMtime    ? &Mtime    : NULL,
 | 
						|
             UpdateMode     ? &Mode     : NULL
 | 
						|
             );
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process an EFI_FILE_INFO setting request.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
SetFileInfo (
 | 
						|
  IN EFI_FILE_PROTOCOL  *This,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN VOID               *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  VIRTIO_FS_FILE  *VirtioFsFile;
 | 
						|
  EFI_STATUS      Status;
 | 
						|
  EFI_FILE_INFO   *FileInfo;
 | 
						|
 | 
						|
  VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate if Buffer passes as EFI_FILE_INFO.
 | 
						|
  //
 | 
						|
  Status = ValidateInfoStructure (
 | 
						|
             BufferSize,                    // SizeByProtocolCaller
 | 
						|
             OFFSET_OF (
 | 
						|
               EFI_FILE_INFO,
 | 
						|
               FileName
 | 
						|
               ) + sizeof (CHAR16),         // MinimumStructSize
 | 
						|
             TRUE,                          // IsSizeByInfoPresent
 | 
						|
             Buffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  FileInfo = Buffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // Perform the rename/move request, if any.
 | 
						|
  //
 | 
						|
  Status = Rename (VirtioFsFile, FileInfo->FileName);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update any attributes requested.
 | 
						|
  //
 | 
						|
  Status = UpdateAttributes (VirtioFsFile, FileInfo);
 | 
						|
  //
 | 
						|
  // The UEFI spec does not speak about partial failure in
 | 
						|
  // EFI_FILE_PROTOCOL.SetInfo(); we won't try to roll back the rename (if
 | 
						|
  // there was one) in case the attribute updates fail.
 | 
						|
  //
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process an EFI_FILE_SYSTEM_INFO setting request.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
SetFileSystemInfo (
 | 
						|
  IN EFI_FILE_PROTOCOL  *This,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN VOID               *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  VIRTIO_FS_FILE        *VirtioFsFile;
 | 
						|
  VIRTIO_FS             *VirtioFs;
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_FILE_SYSTEM_INFO  *FileSystemInfo;
 | 
						|
 | 
						|
  VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
 | 
						|
  VirtioFs     = VirtioFsFile->OwnerFs;
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate if Buffer passes as EFI_FILE_SYSTEM_INFO.
 | 
						|
  //
 | 
						|
  Status = ValidateInfoStructure (
 | 
						|
             BufferSize,                       // SizeByProtocolCaller
 | 
						|
             OFFSET_OF (
 | 
						|
               EFI_FILE_SYSTEM_INFO,
 | 
						|
               VolumeLabel
 | 
						|
               ) + sizeof (CHAR16),            // MinimumStructSize
 | 
						|
             TRUE,                             // IsSizeByInfoPresent
 | 
						|
             Buffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  FileSystemInfo = Buffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // EFI_FILE_SYSTEM_INFO fields other than VolumeLabel cannot be changed, per
 | 
						|
  // spec.
 | 
						|
  //
 | 
						|
  // If the label is being changed to its current value, report success;
 | 
						|
  // otherwise, reject the request, as the Virtio Filesystem device does not
 | 
						|
  // support changing the label.
 | 
						|
  //
 | 
						|
  if (StrCmp (FileSystemInfo->VolumeLabel, VirtioFs->Label) == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_WRITE_PROTECTED;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Process an EFI_FILE_SYSTEM_VOLUME_LABEL setting request.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
SetFileSystemVolumeLabelInfo (
 | 
						|
  IN EFI_FILE_PROTOCOL  *This,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN VOID               *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  VIRTIO_FS_FILE                *VirtioFsFile;
 | 
						|
  VIRTIO_FS                     *VirtioFs;
 | 
						|
  EFI_STATUS                    Status;
 | 
						|
  EFI_FILE_SYSTEM_VOLUME_LABEL  *FileSystemVolumeLabel;
 | 
						|
 | 
						|
  VirtioFsFile = VIRTIO_FS_FILE_FROM_SIMPLE_FILE (This);
 | 
						|
  VirtioFs     = VirtioFsFile->OwnerFs;
 | 
						|
 | 
						|
  //
 | 
						|
  // Validate if Buffer passes as EFI_FILE_SYSTEM_VOLUME_LABEL.
 | 
						|
  //
 | 
						|
  Status = ValidateInfoStructure (
 | 
						|
             BufferSize,                              // SizeByProtocolCaller
 | 
						|
             OFFSET_OF (
 | 
						|
               EFI_FILE_SYSTEM_VOLUME_LABEL,
 | 
						|
               VolumeLabel
 | 
						|
               ) + sizeof (CHAR16),                   // MinimumStructSize
 | 
						|
             FALSE,                                   // IsSizeByInfoPresent
 | 
						|
             Buffer
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  FileSystemVolumeLabel = Buffer;
 | 
						|
 | 
						|
  //
 | 
						|
  // If the label is being changed to its current value, report success;
 | 
						|
  // otherwise, reject the request, as the Virtio Filesystem device does not
 | 
						|
  // support changing the label.
 | 
						|
  //
 | 
						|
  if (StrCmp (FileSystemVolumeLabel->VolumeLabel, VirtioFs->Label) == 0) {
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_WRITE_PROTECTED;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
VirtioFsSimpleFileSetInfo (
 | 
						|
  IN EFI_FILE_PROTOCOL  *This,
 | 
						|
  IN EFI_GUID           *InformationType,
 | 
						|
  IN UINTN              BufferSize,
 | 
						|
  IN VOID               *Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
 | 
						|
    return SetFileInfo (This, BufferSize, Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
 | 
						|
    return SetFileSystemInfo (This, BufferSize, Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | 
						|
    return SetFileSystemVolumeLabelInfo (This, BufferSize, Buffer);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 |