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