FuseOpenDir.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /** @file
  2. FUSE_OPENDIR wrapper for the Virtio Filesystem device.
  3. Copyright (C) 2020, Red Hat, Inc.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "VirtioFsDxe.h"
  7. /**
  8. Send a FUSE_OPENDIR request to the Virtio Filesystem device, for opening a
  9. directory.
  10. The function may only be called after VirtioFsFuseInitSession() returns
  11. successfully and before VirtioFsUninit() is called.
  12. @param[in,out] VirtioFs The Virtio Filesystem device to send the
  13. FUSE_OPENDIR request to. On output, the FUSE request
  14. counter "VirtioFs->RequestId" will have been
  15. incremented.
  16. @param[in] NodeId The inode number of the directory to open.
  17. @param[out] FuseHandle The open file handle returned by the Virtio
  18. Filesystem device.
  19. @retval EFI_SUCCESS The directory has been opened.
  20. @return The "errno" value mapped to an EFI_STATUS code, if the
  21. Virtio Filesystem device explicitly reported an error.
  22. @return Error codes propagated from VirtioFsSgListsValidate(),
  23. VirtioFsFuseNewRequest(), VirtioFsSgListsSubmit(),
  24. VirtioFsFuseCheckResponse().
  25. **/
  26. EFI_STATUS
  27. VirtioFsFuseOpenDir (
  28. IN OUT VIRTIO_FS *VirtioFs,
  29. IN UINT64 NodeId,
  30. OUT UINT64 *FuseHandle
  31. )
  32. {
  33. VIRTIO_FS_FUSE_REQUEST CommonReq;
  34. VIRTIO_FS_FUSE_OPEN_REQUEST OpenReq;
  35. VIRTIO_FS_IO_VECTOR ReqIoVec[2];
  36. VIRTIO_FS_SCATTER_GATHER_LIST ReqSgList;
  37. VIRTIO_FS_FUSE_RESPONSE CommonResp;
  38. VIRTIO_FS_FUSE_OPEN_RESPONSE OpenResp;
  39. VIRTIO_FS_IO_VECTOR RespIoVec[2];
  40. VIRTIO_FS_SCATTER_GATHER_LIST RespSgList;
  41. EFI_STATUS Status;
  42. //
  43. // Set up the scatter-gather lists.
  44. //
  45. ReqIoVec[0].Buffer = &CommonReq;
  46. ReqIoVec[0].Size = sizeof CommonReq;
  47. ReqIoVec[1].Buffer = &OpenReq;
  48. ReqIoVec[1].Size = sizeof OpenReq;
  49. ReqSgList.IoVec = ReqIoVec;
  50. ReqSgList.NumVec = ARRAY_SIZE (ReqIoVec);
  51. RespIoVec[0].Buffer = &CommonResp;
  52. RespIoVec[0].Size = sizeof CommonResp;
  53. RespIoVec[1].Buffer = &OpenResp;
  54. RespIoVec[1].Size = sizeof OpenResp;
  55. RespSgList.IoVec = RespIoVec;
  56. RespSgList.NumVec = ARRAY_SIZE (RespIoVec);
  57. //
  58. // Validate the scatter-gather lists; calculate the total transfer sizes.
  59. //
  60. Status = VirtioFsSgListsValidate (VirtioFs, &ReqSgList, &RespSgList);
  61. if (EFI_ERROR (Status)) {
  62. return Status;
  63. }
  64. //
  65. // Populate the common request header.
  66. //
  67. Status = VirtioFsFuseNewRequest (
  68. VirtioFs,
  69. &CommonReq,
  70. ReqSgList.TotalSize,
  71. VirtioFsFuseOpOpenDir,
  72. NodeId
  73. );
  74. if (EFI_ERROR (Status)) {
  75. return Status;
  76. }
  77. //
  78. // Populate the FUSE_OPENDIR-specific fields.
  79. //
  80. OpenReq.Flags = 0;
  81. OpenReq.Unused = 0;
  82. //
  83. // Submit the request.
  84. //
  85. Status = VirtioFsSgListsSubmit (VirtioFs, &ReqSgList, &RespSgList);
  86. if (EFI_ERROR (Status)) {
  87. return Status;
  88. }
  89. //
  90. // Verify the response (all response buffers are fixed size).
  91. //
  92. Status = VirtioFsFuseCheckResponse (&RespSgList, CommonReq.Unique, NULL);
  93. if (EFI_ERROR (Status)) {
  94. if (Status == EFI_DEVICE_ERROR) {
  95. DEBUG ((
  96. DEBUG_ERROR,
  97. "%a: Label=\"%s\" NodeId=%Lu Errno=%d\n",
  98. __FUNCTION__,
  99. VirtioFs->Label,
  100. NodeId,
  101. CommonResp.Error
  102. ));
  103. Status = VirtioFsErrnoToEfiStatus (CommonResp.Error);
  104. }
  105. return Status;
  106. }
  107. //
  108. // Output the open file handle.
  109. //
  110. *FuseHandle = OpenResp.FileHandle;
  111. return EFI_SUCCESS;
  112. }