text: /** @file
    EFI_SIMPLE_FILE_SYSTEM_PROTOCOL.OpenVolume() member function for the Virtio
    Filesystem driver.
  
    Copyright (C) 2020, Red Hat, Inc.
  
    SPDX-License-Identifier: BSD-2-Clause-Patent
  **/
  
  #include <Library/BaseLib.h>             // InsertTailList()
  #include <Library/MemoryAllocationLib.h> // AllocatePool()
  
  #include "VirtioFsDxe.h"
  
  /**
    Open the root directory on the Virtio Filesystem.
  
    Refer to EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME for the interface
    contract.
  **/
  EFI_STATUS
  EFIAPI
  VirtioFsOpenVolume (
    IN  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
    OUT EFI_FILE_PROTOCOL               **Root
    )
  {
    VIRTIO_FS      *VirtioFs;
    VIRTIO_FS_FILE *VirtioFsFile;
    EFI_STATUS     Status;
    CHAR8          *CanonicalPathname;
    UINT64         RootDirHandle;
  
    VirtioFs = VIRTIO_FS_FROM_SIMPLE_FS (This);
  
    VirtioFsFile = AllocatePool (sizeof *VirtioFsFile);
    if (VirtioFsFile == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }
  
    CanonicalPathname = AllocateCopyPool (sizeof "/", "/");
    if (CanonicalPathname == NULL) {
      Status = EFI_OUT_OF_RESOURCES;
      goto FreeVirtioFsFile;
    }
  
    //
    // Open the root directory.
    //
    Status = VirtioFsFuseOpenDir (VirtioFs, VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID,
               &RootDirHandle);
    if (EFI_ERROR (Status)) {
      goto FreeCanonicalPathname;
    }
  
    //
    // Populate the new VIRTIO_FS_FILE object.
    //
    VirtioFsFile->Signature              = VIRTIO_FS_FILE_SIG;
    VirtioFsFile->SimpleFile.Revision    = EFI_FILE_PROTOCOL_REVISION;
    VirtioFsFile->SimpleFile.Open        = VirtioFsSimpleFileOpen;
    VirtioFsFile->SimpleFile.Close       = VirtioFsSimpleFileClose;
    VirtioFsFile->SimpleFile.Delete      = VirtioFsSimpleFileDelete;
    VirtioFsFile->SimpleFile.Read        = VirtioFsSimpleFileRead;
    VirtioFsFile->SimpleFile.Write       = VirtioFsSimpleFileWrite;
    VirtioFsFile->SimpleFile.GetPosition = VirtioFsSimpleFileGetPosition;
    VirtioFsFile->SimpleFile.SetPosition = VirtioFsSimpleFileSetPosition;
    VirtioFsFile->SimpleFile.GetInfo     = VirtioFsSimpleFileGetInfo;
    VirtioFsFile->SimpleFile.SetInfo     = VirtioFsSimpleFileSetInfo;
    VirtioFsFile->SimpleFile.Flush       = VirtioFsSimpleFileFlush;
    VirtioFsFile->IsDirectory            = TRUE;
    VirtioFsFile->IsOpenForWriting       = FALSE;
    VirtioFsFile->OwnerFs                = VirtioFs;
    VirtioFsFile->CanonicalPathname      = CanonicalPathname;
    VirtioFsFile->FilePosition           = 0;
    VirtioFsFile->NodeId                 = VIRTIO_FS_FUSE_ROOT_DIR_NODE_ID;
    VirtioFsFile->FuseHandle             = RootDirHandle;
    VirtioFsFile->FileInfoArray          = NULL;
    VirtioFsFile->SingleFileInfoSize     = 0;
    VirtioFsFile->NumFileInfo            = 0;
    VirtioFsFile->NextFileInfo           = 0;
  
    //
    // One more file open for the filesystem.
    //
    InsertTailList (&VirtioFs->OpenFiles, &VirtioFsFile->OpenFilesEntry);
  
    *Root = &VirtioFsFile->SimpleFile;
    return EFI_SUCCESS;
  
  FreeCanonicalPathname:
    FreePool (CanonicalPathname);
  
  FreeVirtioFsFile:
    FreePool (VirtioFsFile);
  
    return Status;
  }
  