]> git.proxmox.com Git - mirror_edk2.git/blob - FatPkg/EnhancedFatDxe/Open.c
Change Fat driver to support asynchronous File IO introduced in UEFI spec 2.3.1.D.
[mirror_edk2.git] / FatPkg / EnhancedFatDxe / Open.c
1 /*++
2
3 Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 open.c
16
17 Abstract:
18
19 Routines dealing with file open
20
21 Revision History
22
23 --*/
24
25 #include "Fat.h"
26
27 EFI_STATUS
28 FatAllocateIFile (
29 IN FAT_OFILE *OFile,
30 OUT FAT_IFILE **PtrIFile
31 )
32 /*++
33
34 Routine Description:
35
36 Create an Open instance for the existing OFile.
37 The IFile of the newly opened file is passed out.
38
39 Arguments:
40
41 OFile - The file that serves as a starting reference point.
42 PtrIFile - The newly generated IFile instance.
43
44 Returns:
45
46 EFI_OUT_OF_RESOURCES - Can not allocate the memory for the IFile
47 EFI_SUCCESS - Create the new IFile for the OFile successfully
48
49 --*/
50 {
51 FAT_IFILE *IFile;
52
53 ASSERT_VOLUME_LOCKED (OFile->Volume);
54
55 //
56 // Allocate a new open instance
57 //
58 IFile = AllocateZeroPool (sizeof (FAT_IFILE));
59 if (IFile == NULL) {
60 return EFI_OUT_OF_RESOURCES;
61 }
62
63 IFile->Signature = FAT_IFILE_SIGNATURE;
64
65 CopyMem (&(IFile->Handle), &FatFileInterface, sizeof (EFI_FILE_PROTOCOL));
66
67 //
68 // Report the correct revision number based on the DiskIo2 availability
69 //
70 if (OFile->Volume->DiskIo2 != NULL) {
71 IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION2;
72 } else {
73 IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION;
74 }
75
76 IFile->OFile = OFile;
77 InsertTailList (&OFile->Opens, &IFile->Link);
78 InitializeListHead (&IFile->Tasks);
79
80 *PtrIFile = IFile;
81 return EFI_SUCCESS;
82 }
83
84 EFI_STATUS
85 FatOFileOpen (
86 IN FAT_OFILE *OFile,
87 OUT FAT_IFILE **NewIFile,
88 IN CHAR16 *FileName,
89 IN UINT64 OpenMode,
90 IN UINT8 Attributes
91 )
92 /*++
93
94 Routine Description:
95
96 Open a file for a file name relative to an existing OFile.
97 The IFile of the newly opened file is passed out.
98
99 Arguments:
100
101 OFile - The file that serves as a starting reference point.
102 NewIFile - The newly generated IFile instance.
103 FileName - The file name relative to the OFile.
104 OpenMode - Open mode.
105 Attributes - Attributes to set if the file is created.
106
107 Returns:
108
109 EFI_SUCCESS - Open the file successfully.
110 EFI_INVALID_PARAMETER - The open mode is conflict with the attributes
111 or the file name is not valid.
112 EFI_NOT_FOUND - Conficts between dir intention and attribute.
113 EFI_WRITE_PROTECTED - Can't open for write if the volume is read only.
114 EFI_ACCESS_DENIED - If the file's attribute is read only, and the
115 open is for read-write fail it.
116 EFI_OUT_OF_RESOURCES - Can not allocate the memory.
117
118 --*/
119 {
120 FAT_VOLUME *Volume;
121 EFI_STATUS Status;
122 CHAR16 NewFileName[EFI_PATH_STRING_LENGTH];
123 FAT_DIRENT *DirEnt;
124 UINT8 FileAttributes;
125 BOOLEAN WriteMode;
126
127 Volume = OFile->Volume;
128 ASSERT_VOLUME_LOCKED (Volume);
129 WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE);
130 if (Volume->ReadOnly && WriteMode) {
131 return EFI_WRITE_PROTECTED;
132 }
133 //
134 // Verify the source file handle isn't in an error state
135 //
136 Status = OFile->Error;
137 if (EFI_ERROR (Status)) {
138 return Status;
139 }
140 //
141 // Get new OFile for the file
142 //
143 Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName);
144 if (EFI_ERROR (Status)) {
145 return Status;
146 }
147
148 if (*NewFileName != 0) {
149 //
150 // If there's a remaining part of the name, then we had
151 // better be creating the file in the directory
152 //
153 if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) {
154 return EFI_NOT_FOUND;
155 }
156
157 Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt);
158 if (EFI_ERROR (Status)) {
159 return Status;
160 }
161
162 Status = FatOpenDirEnt (OFile, DirEnt);
163 if (EFI_ERROR (Status)) {
164 return Status;
165 }
166
167 OFile = DirEnt->OFile;
168 if (OFile->ODir != NULL) {
169 //
170 // If we just created a directory, we need to create "." and ".."
171 //
172 Status = FatCreateDotDirEnts (OFile);
173 if (EFI_ERROR (Status)) {
174 return Status;
175 }
176 }
177 }
178 //
179 // If the file's attribute is read only, and the open is for
180 // read-write, then the access is denied.
181 //
182 FileAttributes = OFile->DirEnt->Entry.Attributes;
183 if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) {
184 return EFI_ACCESS_DENIED;
185 }
186 //
187 // Create an open instance of the OFile
188 //
189 Status = FatAllocateIFile (OFile, NewIFile);
190 if (EFI_ERROR (Status)) {
191 return Status;
192 }
193
194 (*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode;
195
196 DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status));
197 return FatOFileFlush (OFile);
198 }
199
200 EFI_STATUS
201 FatOpenEx (
202 IN EFI_FILE_PROTOCOL *FHand,
203 OUT EFI_FILE_PROTOCOL **NewHandle,
204 IN CHAR16 *FileName,
205 IN UINT64 OpenMode,
206 IN UINT64 Attributes,
207 IN OUT EFI_FILE_IO_TOKEN *Token
208 )
209 /*++
210 Routine Description:
211
212 Implements OpenEx() of Simple File System Protocol.
213
214 Arguments:
215
216 FHand - File handle of the file serves as a starting reference point.
217 NewHandle - Handle of the file that is newly opened.
218 FileName - File name relative to FHand.
219 OpenMode - Open mode.
220 Attributes - Attributes to set if the file is created.
221 Token - A pointer to the token associated with the transaction.
222
223 Returns:
224
225 EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
226 The OpenMode is not supported.
227 The Attributes is not the valid attributes.
228 EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
229 EFI_SUCCESS - Open the file successfully.
230 Others - The status of open file.
231
232 --*/
233 {
234 FAT_IFILE *IFile;
235 FAT_IFILE *NewIFile;
236 FAT_OFILE *OFile;
237 EFI_STATUS Status;
238 FAT_TASK *Task;
239
240 //
241 // Perform some parameter checking
242 //
243 if (FileName == NULL) {
244 return EFI_INVALID_PARAMETER;
245 }
246 //
247 // Check for a valid mode
248 //
249 switch (OpenMode) {
250 case EFI_FILE_MODE_READ:
251 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
252 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE:
253 break;
254
255 default:
256 return EFI_INVALID_PARAMETER;
257 }
258
259 //
260 // Check for valid Attributes for file creation case.
261 //
262 if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) {
263 return EFI_INVALID_PARAMETER;
264 }
265
266 IFile = IFILE_FROM_FHAND (FHand);
267 OFile = IFile->OFile;
268 Task = NULL;
269
270 if (Token == NULL) {
271 FatWaitNonblockingTask (IFile);
272 } else {
273 //
274 // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2.
275 // But if it calls, the below check can avoid crash.
276 //
277 if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) {
278 return EFI_UNSUPPORTED;
279 }
280 Task = FatCreateTask (IFile, Token);
281 if (Task == NULL) {
282 return EFI_OUT_OF_RESOURCES;
283 }
284 }
285
286 //
287 // Lock
288 //
289 FatAcquireLock ();
290
291 //
292 // Open the file
293 //
294 Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes);
295
296 //
297 // If the file was opened, return the handle to the caller
298 //
299 if (!EFI_ERROR (Status)) {
300 *NewHandle = &NewIFile->Handle;
301 }
302 //
303 // Unlock
304 //
305 Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task);
306 FatReleaseLock ();
307
308 if (Token != NULL) {
309 if (!EFI_ERROR (Status)) {
310 Status = FatQueueTask (IFile, Task);
311 } else {
312 FatDestroyTask (Task);
313 }
314 }
315
316 return Status;
317 }
318
319 EFI_STATUS
320 EFIAPI
321 FatOpen (
322 IN EFI_FILE_PROTOCOL *FHand,
323 OUT EFI_FILE_PROTOCOL **NewHandle,
324 IN CHAR16 *FileName,
325 IN UINT64 OpenMode,
326 IN UINT64 Attributes
327 )
328 /*++
329 Routine Description:
330
331 Implements Open() of Simple File System Protocol.
332
333 Arguments:
334
335 FHand - File handle of the file serves as a starting reference point.
336 NewHandle - Handle of the file that is newly opened.
337 FileName - File name relative to FHand.
338 OpenMode - Open mode.
339 Attributes - Attributes to set if the file is created.
340
341 Returns:
342
343 EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty.
344 The OpenMode is not supported.
345 The Attributes is not the valid attributes.
346 EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string.
347 EFI_SUCCESS - Open the file successfully.
348 Others - The status of open file.
349
350 --*/
351 {
352 return FatOpenEx (FHand, NewHandle, FileName, OpenMode, Attributes, NULL);
353 }