diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Open.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Open.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Open.c b/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Open.c new file mode 100644 index 00000000..ac00e899 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/FatPkg/EnhancedFatDxe/Open.c @@ -0,0 +1,320 @@ +/** @file + Routines dealing with file open. + +Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Fat.h" + +/** + + Create an Open instance for the existing OFile. + The IFile of the newly opened file is passed out. + + @param OFile - The file that serves as a starting reference point. + @param PtrIFile - The newly generated IFile instance. + + @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory for the IFile + @retval EFI_SUCCESS - Create the new IFile for the OFile successfully + +**/ +EFI_STATUS +FatAllocateIFile ( + IN FAT_OFILE *OFile, + OUT FAT_IFILE **PtrIFile + ) +{ + FAT_IFILE *IFile; + + ASSERT_VOLUME_LOCKED (OFile->Volume); + + // + // Allocate a new open instance + // + IFile = AllocateZeroPool (sizeof (FAT_IFILE)); + if (IFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + IFile->Signature = FAT_IFILE_SIGNATURE; + + CopyMem (&(IFile->Handle), &FatFileInterface, sizeof (EFI_FILE_PROTOCOL)); + + // + // Report the correct revision number based on the DiskIo2 availability + // + if (OFile->Volume->DiskIo2 != NULL) { + IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION2; + } else { + IFile->Handle.Revision = EFI_FILE_PROTOCOL_REVISION; + } + + IFile->OFile = OFile; + InsertTailList (&OFile->Opens, &IFile->Link); + InitializeListHead (&IFile->Tasks); + + *PtrIFile = IFile; + return EFI_SUCCESS; +} + +/** + + Open a file for a file name relative to an existing OFile. + The IFile of the newly opened file is passed out. + + @param OFile - The file that serves as a starting reference point. + @param NewIFile - The newly generated IFile instance. + @param FileName - The file name relative to the OFile. + @param OpenMode - Open mode. + @param Attributes - Attributes to set if the file is created. + + + @retval EFI_SUCCESS - Open the file successfully. + @retval EFI_INVALID_PARAMETER - The open mode is conflict with the attributes + or the file name is not valid. + @retval EFI_NOT_FOUND - Conflicts between dir intention and attribute. + @retval EFI_WRITE_PROTECTED - Can't open for write if the volume is read only. + @retval EFI_ACCESS_DENIED - If the file's attribute is read only, and the + open is for read-write fail it. + @retval EFI_OUT_OF_RESOURCES - Can not allocate the memory. + +**/ +EFI_STATUS +FatOFileOpen ( + IN FAT_OFILE *OFile, + OUT FAT_IFILE **NewIFile, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT8 Attributes + ) +{ + FAT_VOLUME *Volume; + EFI_STATUS Status; + CHAR16 NewFileName[EFI_PATH_STRING_LENGTH]; + FAT_DIRENT *DirEnt; + UINT8 FileAttributes; + BOOLEAN WriteMode; + + DirEnt = NULL; + Volume = OFile->Volume; + ASSERT_VOLUME_LOCKED (Volume); + WriteMode = (BOOLEAN) (OpenMode & EFI_FILE_MODE_WRITE); + if (Volume->ReadOnly && WriteMode) { + return EFI_WRITE_PROTECTED; + } + // + // Verify the source file handle isn't in an error state + // + Status = OFile->Error; + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get new OFile for the file + // + Status = FatLocateOFile (&OFile, FileName, Attributes, NewFileName); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*NewFileName != 0) { + // + // If there's a remaining part of the name, then we had + // better be creating the file in the directory + // + if ((OpenMode & EFI_FILE_MODE_CREATE) == 0) { + return EFI_NOT_FOUND; + } + + Status = FatCreateDirEnt (OFile, NewFileName, Attributes, &DirEnt); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (DirEnt != NULL); + Status = FatOpenDirEnt (OFile, DirEnt); + if (EFI_ERROR (Status)) { + return Status; + } + + OFile = DirEnt->OFile; + if (OFile->ODir != NULL) { + // + // If we just created a directory, we need to create "." and ".." + // + Status = FatCreateDotDirEnts (OFile); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + // + // If the file's attribute is read only, and the open is for + // read-write, then the access is denied. + // + FileAttributes = OFile->DirEnt->Entry.Attributes; + if ((FileAttributes & EFI_FILE_READ_ONLY) != 0 && (FileAttributes & FAT_ATTRIBUTE_DIRECTORY) == 0 && WriteMode) { + return EFI_ACCESS_DENIED; + } + // + // Create an open instance of the OFile + // + Status = FatAllocateIFile (OFile, NewIFile); + if (EFI_ERROR (Status)) { + return Status; + } + + (*NewIFile)->ReadOnly = (BOOLEAN)!WriteMode; + + DEBUG ((EFI_D_INFO, "FSOpen: Open '%S' %r\n", FileName, Status)); + return FatOFileFlush (OFile); +} + +/** + + 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; +} + +/** + + Implements Open() 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. + + @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 +FatOpen ( + IN EFI_FILE_PROTOCOL *FHand, + OUT EFI_FILE_PROTOCOL **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +{ + return FatOpenEx (FHand, NewHandle, FileName, OpenMode, Attributes, NULL); +} |