/** Implements OpenEx() of Simple File System Protocol. @param FHand - File handle of the file serves as a starting reference point. @param NewHandle - Handle of the file that is newly opened. @param FileName - File name relative to FHand. @param OpenMode - Open mode. @param Attributes - Attributes to set if the file is created. @param Token - A pointer to the token associated with the transaction.: @retval EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty. The OpenMode is not supported. The Attributes is not the valid attributes. @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string. @retval EFI_SUCCESS - Open the file successfully. @return Others - The status of open file. **/ EFI_STATUS 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 ) { FAT_IFILE *IFile; FAT_IFILE *NewIFile; FAT_OFILE *OFile; EFI_STATUS Status; FAT_TASK *Task; // // Perform some parameter checking // if (FileName == NULL) { return EFI_INVALID_PARAMETER; } // // Check for a valid mode // switch (OpenMode) { case EFI_FILE_MODE_READ: case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE: break; default: return EFI_INVALID_PARAMETER; } // // Check for valid Attributes for file creation case. // if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) { return EFI_INVALID_PARAMETER; } IFile = IFILE_FROM_FHAND (FHand); OFile = IFile->OFile; Task = NULL; if (Token == NULL) { FatWaitNonblockingTask (IFile); } else { // // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2. // But if it calls, the below check can avoid crash. // if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) { return EFI_UNSUPPORTED; } Task = FatCreateTask (IFile, Token); if (Task == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Lock // FatAcquireLock (); // // Open the file // Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes); // // If the file was opened, return the handle to the caller // if (!EFI_ERROR (Status)) { *NewHandle = &NewIFile->Handle; } // // Unlock // Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task); FatReleaseLock (); if (Token != NULL) { if (!EFI_ERROR (Status)) { Status = FatQueueTask (IFile, Task); } else { FatDestroyTask (Task); } } return Status; }
EFI_STATUS FatIFileAccess ( IN EFI_FILE_PROTOCOL *FHand, IN IO_MODE IoMode, IN OUT UINTN *BufferSize, IN OUT VOID *Buffer, IN EFI_FILE_IO_TOKEN *Token ) /*++ Routine Description: Get the file info from the open file of the IFile into Buffer. Arguments: FHand - The file handle to access. IoMode - Indicate whether the access mode is reading or writing. BufferSize - Size of Buffer. Buffer - Buffer containing read data. Token - A pointer to the token associated with the transaction. Returns: EFI_SUCCESS - Get the file info successfully. EFI_DEVICE_ERROR - Can not find the OFile for the file. EFI_VOLUME_CORRUPTED - The file type of open file is error. EFI_WRITE_PROTECTED - The disk is write protect. EFI_ACCESS_DENIED - The file is read-only. other - An error occurred when operating on the disk. --*/ { EFI_STATUS Status; FAT_IFILE *IFile; FAT_OFILE *OFile; FAT_VOLUME *Volume; UINT64 EndPosition; FAT_TASK *Task; IFile = IFILE_FROM_FHAND (FHand); OFile = IFile->OFile; Volume = OFile->Volume; Task = NULL; // // Write to a directory is unsupported // if ((OFile->ODir != NULL) && (IoMode == WRITE_DATA)) { return EFI_UNSUPPORTED; } if (OFile->Error == EFI_NOT_FOUND) { return EFI_DEVICE_ERROR; } if (IoMode == READ_DATA) { // // If position is at EOF, then return device error // if (IFile->Position > OFile->FileSize) { return EFI_DEVICE_ERROR; } } else { // // Check if the we can write data // if (Volume->ReadOnly) { return EFI_WRITE_PROTECTED; } if (IFile->ReadOnly) { return EFI_ACCESS_DENIED; } } if (Token == NULL) { FatWaitNonblockingTask (IFile); } else { // // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2. // But if it calls, the below check can avoid crash. // if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) { return EFI_UNSUPPORTED; } Task = FatCreateTask (IFile, Token); if (Task == NULL) { return EFI_OUT_OF_RESOURCES; } } FatAcquireLock (); Status = OFile->Error; if (!EFI_ERROR (Status)) { if (OFile->ODir != NULL) { // // Read a directory is supported // ASSERT (IoMode == READ_DATA); Status = FatIFileReadDir (IFile, BufferSize, Buffer); OFile = NULL; } else { // // Access a file // EndPosition = IFile->Position + *BufferSize; if (EndPosition > OFile->FileSize) { // // The position goes beyond the end of file // if (IoMode == READ_DATA) { // // Adjust the actual size read // *BufferSize -= (UINTN) EndPosition - OFile->FileSize; } else { // // We expand the file size of OFile // Status = FatGrowEof (OFile, EndPosition); if (EFI_ERROR (Status)) { // // Must update the file's info into the file's Directory Entry // and then flush the dirty cache info into disk. // *BufferSize = 0; FatOFileFlush (OFile); OFile = NULL; goto Done; } FatUpdateDirEntClusterSizeInfo (OFile); } } Status = FatAccessOFile (OFile, IoMode, (UINTN) IFile->Position, BufferSize, Buffer, Task); IFile->Position += *BufferSize; } } if (Token != NULL) { if (!EFI_ERROR (Status)) { Status = FatQueueTask (IFile, Task); } else { FatDestroyTask (Task); } } Done: // // On EFI_SUCCESS case, not calling FatCleanupVolume(): // 1) The Cache flush operation is avoided to enhance // performance. Caller is responsible to call Flush() when necessary. // 2) The volume dirty bit is probably set already, and is expected to be // cleaned in subsequent Flush() or other operations. // 3) Write operation doesn't affect OFile/IFile structure, so // Reference checking is not necessary. // if (EFI_ERROR (Status)) { Status = FatCleanupVolume (Volume, OFile, Status, NULL); } FatReleaseLock (); return Status; }
EFI_STATUS 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 ) /*++ Routine Description: Implements OpenEx() of Simple File System Protocol. Arguments: FHand - File handle of the file serves as a starting reference point. NewHandle - Handle of the file that is newly opened. FileName - File name relative to FHand. OpenMode - Open mode. Attributes - Attributes to set if the file is created. Token - A pointer to the token associated with the transaction. Returns: EFI_INVALID_PARAMETER - The FileName is NULL or the file string is empty. The OpenMode is not supported. The Attributes is not the valid attributes. EFI_OUT_OF_RESOURCES - Can not allocate the memory for file string. EFI_SUCCESS - Open the file successfully. Others - The status of open file. --*/ { FAT_IFILE *IFile; FAT_IFILE *NewIFile; FAT_OFILE *OFile; EFI_STATUS Status; FAT_TASK *Task; // // Perform some parameter checking // if (FileName == NULL) { return EFI_INVALID_PARAMETER; } // // Check for a valid mode // switch (OpenMode) { case EFI_FILE_MODE_READ: case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE: break; default: return EFI_INVALID_PARAMETER; } // // Check for valid Attributes for file creation case. // if (((OpenMode & EFI_FILE_MODE_CREATE) != 0) && (Attributes & (EFI_FILE_READ_ONLY | (~EFI_FILE_VALID_ATTR))) != 0) { return EFI_INVALID_PARAMETER; } IFile = IFILE_FROM_FHAND (FHand); OFile = IFile->OFile; Task = NULL; if (Token == NULL) { FatWaitNonblockingTask (IFile); } else { // // Caller shouldn't call the non-blocking interfaces if the low layer doesn't support DiskIo2. // But if it calls, the below check can avoid crash. // if (FHand->Revision < EFI_FILE_PROTOCOL_REVISION2) { return EFI_UNSUPPORTED; } Task = FatCreateTask (IFile, Token); if (Task == NULL) { return EFI_OUT_OF_RESOURCES; } } // // Lock // FatAcquireLock (); // // Open the file // Status = FatOFileOpen (OFile, &NewIFile, FileName, OpenMode, (UINT8) Attributes); // // If the file was opened, return the handle to the caller // if (!EFI_ERROR (Status)) { *NewHandle = &NewIFile->Handle; } // // Unlock // Status = FatCleanupVolume (OFile->Volume, NULL, Status, Task); FatReleaseLock (); if (Token != NULL) { if (!EFI_ERROR (Status)) { Status = FatQueueTask (IFile, Task); } else { FatDestroyTask (Task); } } return Status; }