Open.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /** @file
  2. Routines dealing with file open.
  3. Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Fat.h"
  7. /**
  8. Create an Open instance for the existing OFile.
  9. The IFile of the newly opened file is passed out.
  10. @param OFile - The file that serves as a starting reference point.
  11. @param PtrIFile - The newly generated IFile instance.
  12. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory for the IFile
  13. @retval EFI_SUCCESS - Create the new IFile for the OFile successfully
  14. **/
  15. EFI_STATUS
  16. FatAllocateIFile (
  17. IN FAT_OFILE *OFile,
  18. OUT FAT_IFILE **PtrIFile
  19. )
  20. {
  21. FAT_IFILE *IFile;
  22. ASSERT_VOLUME_LOCKED (OFile->Volume);
  23. //
  24. // Allocate a new open instance
  25. //
  26. IFile = AllocateZeroPool (sizeof (FAT_IFILE));
  27. if (IFile == NULL) {
  28. return EFI_OUT_OF_RESOURCES;
  29. }
  30. IFile->Signature = FAT_IFILE_SIGNATURE;
  31. CopyMem (&(IFile->Handle), &FatFileInterface, sizeof (EFI_FILE_PROTOCOL));
  32. //
  33. // Report the correct revision number based on the DiskIo2 availability
  34. //
  35. if (OFile->Volume->DiskIo2 != NULL) {
  36. IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION2;
  37. } else {
  38. IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION;
  39. }
  40. IFile->OFile = OFile;
  41. InsertTailList (&OFile->Opens, &IFile->Link);
  42. InitializeListHead (&IFile->Tasks);
  43. *PtrIFile = IFile;
  44. return EFI_SUCCESS;
  45. }
  46. /**
  47. Open a file for a file name relative to an existing OFile.
  48. The IFile of the newly opened file is passed out.
  49. @param OFile - The file that serves as a starting reference point.
  50. @param NewIFile - The newly generated IFile instance.
  51. @param FileName - The file name relative to the OFile.
  52. @param OpenMode - Open mode.
  53. @param Attributes - Attributes to set if the file is created.
  54. @retval EFI_SUCCESS - Open the file successfully.
  55. @retval EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
  56. or the file name is not valid.
  57. @retval EFI_NOT_FOUND - Conficts between dir intention and attribute.
  58. @retval EFI_WRITE_PROTECTED - Can't open for write if the volume is read only.
  59. @retval EFI_ACCESS_DENIED - If the file's attribute is read only, and the
  60. open is for read-write fail it.
  61. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory.
  62. **/
  63. EFI_STATUS
  64. FatOFileOpen (
  65. IN FAT_OFILE *OFile,
  66. OUT FAT_IFILE **NewIFile,
  67. IN CHAR16 *FileName,
  68. IN UINT64 OpenMode,
  69. IN UINT8 Attributes
  70. )
  71. {
  72. FAT_VOLUME *Volume;
  73. EFI_STATUS Status;
  74. CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
  75. FAT_DIRENT *DirEnt;
  76. UINT8 FileAttributes;
  77. BOOLEAN WriteMode;
  78. DirEnt = NULL;
  79. Volume = OFile->Volume;
  80. ASSERT_VOLUME_LOCKED (Volume);
  81. WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
  82. if (Volume->ReadOnly && WriteMode) {
  83. return EFI_WRITE_PROTECTED;
  84. }
  85. //
  86. // Verify the source file handle isn't in an error state
  87. //
  88. Status = OFile->Error;
  89. if (EFI_ERROR (Status)) {
  90. return Status;
  91. }
  92. //
  93. // Get new OFile for the file
  94. //
  95. Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
  96. if (EFI_ERROR (Status)) {
  97. return Status;
  98. }
  99. if (*NewFileName != 0) {
  100. //
  101. // If there's a remaining part of the name, then we had
  102. // better be creating the file in the directory
  103. //
  104. if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
  105. return EFI_NOT_FOUND;
  106. }
  107. Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
  108. if (EFI_ERROR (Status)) {
  109. return Status;
  110. }
  111. ASSERT (DirEnt != NULL);
  112. Status = FatOpenDirEnt (OFile, DirEnt);
  113. if (EFI_ERROR (Status)) {
  114. return Status;
  115. }
  116. OFile = DirEnt->OFile;
  117. if (OFile->ODir != NULL) {
  118. //
  119. // If we just created a directory, we need to create "." and ".."
  120. //
  121. Status = FatCreateDotDirEnts (OFile);
  122. if (EFI_ERROR (Status)) {
  123. return Status;
  124. }
  125. }
  126. }
  127. //
  128. // If the file's attribute is read only, and the open is for
  129. // read-write, then the access is denied.
  130. //
  131. FileAttributes = OFile->DirEnt->Entry.Attributes;
  132. if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
  133. return EFI_ACCESS_DENIED;
  134. }
  135. //
  136. // Create an open instance of the OFile
  137. //
  138. Status = FatAllocateIFile (OFile, NewIFile);
  139. if (EFI_ERROR (Status)) {
  140. return Status;
  141. }
  142. (*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;
  143. DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
  144. return FatOFileFlush (OFile);
  145. }
  146. /**
  147. Implements OpenEx() of Simple File System Protocol.
  148. @param FHand - File handle of the file serves as a starting reference point.
  149. @param NewHandle - Handle of the file that is newly opened.
  150. @param FileName - File name relative to FHand.
  151. @param OpenMode - Open mode.
  152. @param Attributes - Attributes to set if the file is created.
  153. @param Token - A pointer to the token associated with the transaction.:
  154. @retval EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
  155. The OpenMode is not supported.
  156. The Attributes is not the valid attributes.
  157. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
  158. @retval EFI_SUCCESS - Open the file successfully.
  159. @return Others - The status of open file.
  160. **/
  161. EFI_STATUS
  162. EFIAPI
  163. FatOpenEx (
  164. IN EFI_FILE_PROTOCOL *FHand,
  165. OUT EFI_FILE_PROTOCOL **NewHandle,
  166. IN CHAR16 *FileName,
  167. IN UINT64 OpenMode,
  168. IN UINT64 Attributes,
  169. IN OUT EFI_FILE_IO_TOKEN *Token
  170. )
  171. {
  172. FAT_IFILE *IFile;
  173. FAT_IFILE *NewIFile;
  174. FAT_OFILE *OFile;
  175. EFI_STATUS Status;
  176. FAT_TASK *Task;
  177. //
  178. // Perform some parameter checking
  179. //
  180. if (FileName == NULL) {
  181. return EFI_INVALID_PARAMETER;
  182. }
  183. //
  184. // Check for a valid mode
  185. //
  186. switch (OpenMode) {
  187. case EFI_FILE_MODE_READ:
  188. case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
  189. case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
  190. break;
  191. default:
  192. return EFI_INVALID_PARAMETER;
  193. }
  194. //
  195. // Check for valid Attributes for file creation case.
  196. //
  197. if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) {
  198. return EFI_INVALID_PARAMETER;
  199. }
  200. IFile = IFILE_FROM_FHAND (FHand);
  201. OFile = IFile->OFile;
  202. Task = NULL;
  203. if (Token == NULL) {
  204. FatWaitNonblockingTask (IFile);
  205. } else {
  206. //
  207. // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
  208. // But if it calls, the below check can avoid crash.
  209. //
  210. if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
  211. return EFI_UNSUPPORTED;
  212. }
  213. Task = FatCreateTask (IFile, Token);
  214. if (Task == NULL) {
  215. return EFI_OUT_OF_RESOURCES;
  216. }
  217. }
  218. //
  219. // Lock
  220. //
  221. FatAcquireLock ();
  222. //
  223. // Open the file
  224. //
  225. Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);
  226. //
  227. // If the file was opened, return the handle to the caller
  228. //
  229. if (!EFI_ERROR (Status)) {
  230. *NewHandle = &NewIFile->Handle;
  231. }
  232. //
  233. // Unlock
  234. //
  235. Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task);
  236. FatReleaseLock ();
  237. if (Token != NULL) {
  238. if (!EFI_ERROR (Status)) {
  239. Status = FatQueueTask (IFile, Task);
  240. } else {
  241. FatDestroyTask (Task);
  242. }
  243. }
  244. return Status;
  245. }
  246. /**
  247. Implements Open() of Simple File System Protocol.
  248. @param FHand - File handle of the file serves as a starting reference point.
  249. @param NewHandle - Handle of the file that is newly opened.
  250. @param FileName - File name relative to FHand.
  251. @param OpenMode - Open mode.
  252. @param Attributes - Attributes to set if the file is created.
  253. @retval EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
  254. The OpenMode is not supported.
  255. The Attributes is not the valid attributes.
  256. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
  257. @retval EFI_SUCCESS - Open the file successfully.
  258. @return Others - The status of open file.
  259. **/
  260. EFI_STATUS
  261. EFIAPI
  262. FatOpen (
  263. IN EFI_FILE_PROTOCOL *FHand,
  264. OUT EFI_FILE_PROTOCOL **NewHandle,
  265. IN CHAR16 *FileName,
  266. IN UINT64 OpenMode,
  267. IN UINT64 Attributes
  268. )
  269. {
  270. return FatOpenEx (FHand, NewHandle, FileName, OpenMode, Attributes, NULL);
  271. }