Home | History | Annotate | Download | only in EnhancedFatDxe
      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