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 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 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 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 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