REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the MdeModulePkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>
		
			
				
	
	
		
			918 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			918 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Handle operations in files and directories from UDF/ECMA-167 file systems.
 | |
| 
 | |
|   Copyright (C) 2014-2017 Paulo Alcantara <pcacjr@zytor.com>
 | |
|   Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| **/
 | |
| 
 | |
| #include "Udf.h"
 | |
| 
 | |
| EFI_FILE_PROTOCOL  gUdfFileIoOps = {
 | |
|   EFI_FILE_PROTOCOL_REVISION,
 | |
|   UdfOpen,
 | |
|   UdfClose,
 | |
|   UdfDelete,
 | |
|   UdfRead,
 | |
|   UdfWrite,
 | |
|   UdfGetPosition,
 | |
|   UdfSetPosition,
 | |
|   UdfGetInfo,
 | |
|   UdfSetInfo,
 | |
|   UdfFlush,
 | |
|   NULL,
 | |
|   NULL,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| #define _ROOT_FILE(_PrivData)  (_PrivData)->Root
 | |
| #define _PARENT_FILE(_PrivData) \
 | |
|   ((_PrivData)->IsRootDirectory ? (_PrivData)->Root : &(_PrivData)->File)
 | |
| #define _FILE(_PrivData)  _PARENT_FILE(_PrivData)
 | |
| 
 | |
| /**
 | |
|   Open the root directory on a volume.
 | |
| 
 | |
|   @param  This Protocol instance pointer.
 | |
|   @param  Root Returns an Open file handle for the root directory
 | |
| 
 | |
|   @retval EFI_SUCCESS          The device was opened.
 | |
|   @retval EFI_UNSUPPORTED      This volume does not support the file system.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_ACCESS_DENIED    The service denied access to the file.
 | |
|   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
 | |
|                                resources.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfOpenVolume (
 | |
|   IN   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *This,
 | |
|   OUT  EFI_FILE_PROTOCOL                **Root
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                     OldTpl;
 | |
|   EFI_STATUS                  Status;
 | |
|   PRIVATE_UDF_SIMPLE_FS_DATA  *PrivFsData;
 | |
|   PRIVATE_UDF_FILE_DATA       *PrivFileData;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   if ((This == NULL) || (Root == NULL)) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Error_Invalid_Params;
 | |
|   }
 | |
| 
 | |
|   PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivFsData->OpenFiles == 0) {
 | |
|     //
 | |
|     // There is no more open files. Read volume information again since it was
 | |
|     // cleaned up on the last UdfClose() call.
 | |
|     //
 | |
|     Status = ReadUdfVolumeInformation (
 | |
|                PrivFsData->BlockIo,
 | |
|                PrivFsData->DiskIo,
 | |
|                &PrivFsData->Volume
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Error_Read_Udf_Volume;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   CleanupFileInformation (&PrivFsData->Root);
 | |
| 
 | |
|   //
 | |
|   // Find root directory file.
 | |
|   //
 | |
|   Status = FindRootDirectory (
 | |
|              PrivFsData->BlockIo,
 | |
|              PrivFsData->DiskIo,
 | |
|              &PrivFsData->Volume,
 | |
|              &PrivFsData->Root
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Error_Find_Root_Dir;
 | |
|   }
 | |
| 
 | |
|   PrivFileData =
 | |
|     (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
 | |
|   if (PrivFileData == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error_Alloc_Priv_File_Data;
 | |
|   }
 | |
| 
 | |
|   PrivFileData->Signature       = PRIVATE_UDF_FILE_DATA_SIGNATURE;
 | |
|   PrivFileData->SimpleFs        = This;
 | |
|   PrivFileData->Root            = &PrivFsData->Root;
 | |
|   PrivFileData->IsRootDirectory = TRUE;
 | |
| 
 | |
|   CopyMem (
 | |
|     (VOID *)&PrivFileData->FileIo,
 | |
|     (VOID *)&gUdfFileIoOps,
 | |
|     sizeof (EFI_FILE_PROTOCOL)
 | |
|     );
 | |
| 
 | |
|   *Root = &PrivFileData->FileIo;
 | |
| 
 | |
|   PrivFsData->OpenFiles++;
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| 
 | |
| Error_Alloc_Priv_File_Data:
 | |
|   CleanupFileInformation (&PrivFsData->Root);
 | |
| 
 | |
| Error_Find_Root_Dir:
 | |
| 
 | |
| Error_Read_Udf_Volume:
 | |
| Error_Invalid_Params:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Opens a new file relative to the source file's location.
 | |
| 
 | |
|   @param  This       The protocol instance pointer.
 | |
|   @param  NewHandle  Returns File Handle for FileName.
 | |
|   @param  FileName   Null terminated string. "\", ".", and ".." are supported.
 | |
|   @param  OpenMode   Open mode for file.
 | |
|   @param  Attributes Only used for EFI_FILE_MODE_CREATE.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The device was opened.
 | |
|   @retval EFI_NOT_FOUND        The specified file could not be found on the
 | |
|                                device.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_MEDIA_CHANGED    The media has changed.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_ACCESS_DENIED    The service denied access to the file.
 | |
|   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of
 | |
|                                resources.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfOpen (
 | |
|   IN   EFI_FILE_PROTOCOL  *This,
 | |
|   OUT  EFI_FILE_PROTOCOL  **NewHandle,
 | |
|   IN   CHAR16             *FileName,
 | |
|   IN   UINT64             OpenMode,
 | |
|   IN   UINT64             Attributes
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                     OldTpl;
 | |
|   EFI_STATUS                  Status;
 | |
|   PRIVATE_UDF_FILE_DATA       *PrivFileData;
 | |
|   PRIVATE_UDF_SIMPLE_FS_DATA  *PrivFsData;
 | |
|   CHAR16                      FilePath[UDF_PATH_LENGTH];
 | |
|   UDF_FILE_INFO               File;
 | |
|   PRIVATE_UDF_FILE_DATA       *NewPrivFileData;
 | |
|   CHAR16                      *TempFileName;
 | |
| 
 | |
|   ZeroMem (FilePath, sizeof FilePath);
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   if ((This == NULL) || (NewHandle == NULL) || (FileName == NULL)) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Error_Invalid_Params;
 | |
|   }
 | |
| 
 | |
|   if (OpenMode != EFI_FILE_MODE_READ) {
 | |
|     Status = EFI_WRITE_PROTECTED;
 | |
|     goto Error_Invalid_Params;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
 | |
| 
 | |
|   //
 | |
|   // Build full path
 | |
|   //
 | |
|   if (*FileName == L'\\') {
 | |
|     StrCpyS (FilePath, UDF_PATH_LENGTH, FileName);
 | |
|   } else {
 | |
|     StrCpyS (FilePath, UDF_PATH_LENGTH, PrivFileData->AbsoluteFileName);
 | |
|     StrCatS (FilePath, UDF_PATH_LENGTH, L"\\");
 | |
|     StrCatS (FilePath, UDF_PATH_LENGTH, FileName);
 | |
|   }
 | |
| 
 | |
|   MangleFileName (FilePath);
 | |
|   if (FilePath[0] == L'\0') {
 | |
|     Status = EFI_NOT_FOUND;
 | |
|     goto Error_Bad_FileName;
 | |
|   }
 | |
| 
 | |
|   Status = FindFile (
 | |
|              PrivFsData->BlockIo,
 | |
|              PrivFsData->DiskIo,
 | |
|              &PrivFsData->Volume,
 | |
|              FilePath,
 | |
|              _ROOT_FILE (PrivFileData),
 | |
|              _PARENT_FILE (PrivFileData),
 | |
|              &_PARENT_FILE (PrivFileData)->FileIdentifierDesc->Icb,
 | |
|              &File
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Error_Find_File;
 | |
|   }
 | |
| 
 | |
|   NewPrivFileData =
 | |
|     (PRIVATE_UDF_FILE_DATA *)AllocateZeroPool (sizeof (PRIVATE_UDF_FILE_DATA));
 | |
|   if (NewPrivFileData == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Error_Alloc_New_Priv_File_Data;
 | |
|   }
 | |
| 
 | |
|   CopyMem (
 | |
|     (VOID *)NewPrivFileData,
 | |
|     (VOID *)PrivFileData,
 | |
|     sizeof (PRIVATE_UDF_FILE_DATA)
 | |
|     );
 | |
|   CopyMem ((VOID *)&NewPrivFileData->File, &File, sizeof (UDF_FILE_INFO));
 | |
| 
 | |
|   NewPrivFileData->IsRootDirectory = FALSE;
 | |
| 
 | |
|   StrCpyS (NewPrivFileData->AbsoluteFileName, UDF_PATH_LENGTH, FilePath);
 | |
|   FileName = NewPrivFileData->AbsoluteFileName;
 | |
| 
 | |
|   while ((TempFileName = StrStr (FileName, L"\\")) != NULL) {
 | |
|     FileName = TempFileName + 1;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (NewPrivFileData->FileName, UDF_FILENAME_LENGTH, FileName);
 | |
| 
 | |
|   Status = GetFileSize (
 | |
|              PrivFsData->BlockIo,
 | |
|              PrivFsData->DiskIo,
 | |
|              &PrivFsData->Volume,
 | |
|              &NewPrivFileData->File,
 | |
|              &NewPrivFileData->FileSize
 | |
|              );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((
 | |
|       DEBUG_ERROR,
 | |
|       "%a: GetFileSize() fails with status - %r.\n",
 | |
|       __FUNCTION__,
 | |
|       Status
 | |
|       ));
 | |
|     goto Error_Get_File_Size;
 | |
|   }
 | |
| 
 | |
|   NewPrivFileData->FilePosition = 0;
 | |
|   ZeroMem (
 | |
|     (VOID *)&NewPrivFileData->ReadDirInfo,
 | |
|     sizeof (UDF_READ_DIRECTORY_INFO)
 | |
|     );
 | |
| 
 | |
|   *NewHandle = &NewPrivFileData->FileIo;
 | |
| 
 | |
|   PrivFsData->OpenFiles++;
 | |
| 
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| 
 | |
| Error_Get_File_Size:
 | |
|   FreePool ((VOID *)NewPrivFileData);
 | |
| 
 | |
| Error_Alloc_New_Priv_File_Data:
 | |
|   CleanupFileInformation (&File);
 | |
| 
 | |
| Error_Find_File:
 | |
| Error_Bad_FileName:
 | |
| Error_Invalid_Params:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Read data from the file.
 | |
| 
 | |
|   @param  This       Protocol instance pointer.
 | |
|   @param  BufferSize On input size of buffer, on output amount of data in
 | |
|                      buffer.
 | |
|   @param  Buffer     The buffer in which data is read.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was read.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_BUFFER_TO_SMALL  BufferSize is too small. BufferSize contains
 | |
|                                required size.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfRead (
 | |
|   IN      EFI_FILE_PROTOCOL  *This,
 | |
|   IN OUT  UINTN              *BufferSize,
 | |
|   OUT     VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                         OldTpl;
 | |
|   EFI_STATUS                      Status;
 | |
|   PRIVATE_UDF_FILE_DATA           *PrivFileData;
 | |
|   PRIVATE_UDF_SIMPLE_FS_DATA      *PrivFsData;
 | |
|   UDF_VOLUME_INFO                 *Volume;
 | |
|   UDF_FILE_INFO                   *Parent;
 | |
|   UDF_READ_DIRECTORY_INFO         *ReadDirInfo;
 | |
|   EFI_BLOCK_IO_PROTOCOL           *BlockIo;
 | |
|   EFI_DISK_IO_PROTOCOL            *DiskIo;
 | |
|   UDF_FILE_INFO                   FoundFile;
 | |
|   UDF_FILE_IDENTIFIER_DESCRIPTOR  *NewFileIdentifierDesc;
 | |
|   VOID                            *NewFileEntryData;
 | |
|   CHAR16                          FileName[UDF_FILENAME_LENGTH];
 | |
|   UINT64                          FileSize;
 | |
|   UINT64                          BufferSizeUint64;
 | |
| 
 | |
|   ZeroMem (FileName, sizeof FileName);
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   if ((This == NULL) || (BufferSize == NULL) || ((*BufferSize != 0) &&
 | |
|                                                  (Buffer == NULL)))
 | |
|   {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Error_Invalid_Params;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
|   PrivFsData   = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
 | |
| 
 | |
|   BlockIo               = PrivFsData->BlockIo;
 | |
|   DiskIo                = PrivFsData->DiskIo;
 | |
|   Volume                = &PrivFsData->Volume;
 | |
|   ReadDirInfo           = &PrivFileData->ReadDirInfo;
 | |
|   NewFileIdentifierDesc = NULL;
 | |
|   NewFileEntryData      = NULL;
 | |
| 
 | |
|   Parent = _PARENT_FILE (PrivFileData);
 | |
| 
 | |
|   Status = EFI_VOLUME_CORRUPTED;
 | |
| 
 | |
|   if (IS_FID_NORMAL_FILE (Parent->FileIdentifierDesc)) {
 | |
|     if (PrivFileData->FilePosition > PrivFileData->FileSize) {
 | |
|       //
 | |
|       // File's position is beyond the EOF
 | |
|       //
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Error_File_Beyond_The_Eof;
 | |
|     }
 | |
| 
 | |
|     if (PrivFileData->FilePosition == PrivFileData->FileSize) {
 | |
|       *BufferSize = 0;
 | |
|       Status      = EFI_SUCCESS;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     BufferSizeUint64 = *BufferSize;
 | |
| 
 | |
|     Status = ReadFileData (
 | |
|                BlockIo,
 | |
|                DiskIo,
 | |
|                Volume,
 | |
|                Parent,
 | |
|                PrivFileData->FileSize,
 | |
|                &PrivFileData->FilePosition,
 | |
|                Buffer,
 | |
|                &BufferSizeUint64
 | |
|                );
 | |
|     ASSERT (BufferSizeUint64 <= MAX_UINTN);
 | |
|     *BufferSize = (UINTN)BufferSizeUint64;
 | |
|   } else if (IS_FID_DIRECTORY_FILE (Parent->FileIdentifierDesc)) {
 | |
|     if ((ReadDirInfo->FidOffset == 0) && (PrivFileData->FilePosition > 0)) {
 | |
|       Status      = EFI_DEVICE_ERROR;
 | |
|       *BufferSize = 0;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     for ( ; ;) {
 | |
|       Status = ReadDirectoryEntry (
 | |
|                  BlockIo,
 | |
|                  DiskIo,
 | |
|                  Volume,
 | |
|                  &Parent->FileIdentifierDesc->Icb,
 | |
|                  Parent->FileEntry,
 | |
|                  ReadDirInfo,
 | |
|                  &NewFileIdentifierDesc
 | |
|                  );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         if (Status == EFI_DEVICE_ERROR) {
 | |
|           FreePool (ReadDirInfo->DirectoryData);
 | |
|           ZeroMem ((VOID *)ReadDirInfo, sizeof (UDF_READ_DIRECTORY_INFO));
 | |
| 
 | |
|           *BufferSize = 0;
 | |
|           Status      = EFI_SUCCESS;
 | |
|         }
 | |
| 
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // After calling function ReadDirectoryEntry(), if 'NewFileIdentifierDesc'
 | |
|       // is NULL, then the 'Status' must be EFI_OUT_OF_RESOURCES. Hence, if the
 | |
|       // code reaches here, 'NewFileIdentifierDesc' must be not NULL.
 | |
|       //
 | |
|       // The ASSERT here is for addressing a false positive NULL pointer
 | |
|       // dereference issue raised from static analysis.
 | |
|       //
 | |
|       ASSERT (NewFileIdentifierDesc != NULL);
 | |
| 
 | |
|       if (!IS_FID_PARENT_FILE (NewFileIdentifierDesc)) {
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       FreePool ((VOID *)NewFileIdentifierDesc);
 | |
|     }
 | |
| 
 | |
|     Status = FindFileEntry (
 | |
|                BlockIo,
 | |
|                DiskIo,
 | |
|                Volume,
 | |
|                &NewFileIdentifierDesc->Icb,
 | |
|                &NewFileEntryData
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Error_Find_Fe;
 | |
|     }
 | |
| 
 | |
|     ASSERT (NewFileEntryData != NULL);
 | |
| 
 | |
|     if (FE_ICB_FILE_TYPE (NewFileEntryData) == UdfFileEntrySymlink) {
 | |
|       Status = ResolveSymlink (
 | |
|                  BlockIo,
 | |
|                  DiskIo,
 | |
|                  Volume,
 | |
|                  Parent,
 | |
|                  NewFileEntryData,
 | |
|                  &FoundFile
 | |
|                  );
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Error_Resolve_Symlink;
 | |
|       }
 | |
| 
 | |
|       FreePool ((VOID *)NewFileEntryData);
 | |
|       NewFileEntryData = FoundFile.FileEntry;
 | |
| 
 | |
|       Status = GetFileNameFromFid (NewFileIdentifierDesc, ARRAY_SIZE (FileName), FileName);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         FreePool ((VOID *)FoundFile.FileIdentifierDesc);
 | |
|         goto Error_Get_FileName;
 | |
|       }
 | |
| 
 | |
|       FreePool ((VOID *)NewFileIdentifierDesc);
 | |
|       NewFileIdentifierDesc = FoundFile.FileIdentifierDesc;
 | |
|     } else {
 | |
|       FoundFile.FileIdentifierDesc = NewFileIdentifierDesc;
 | |
|       FoundFile.FileEntry          = NewFileEntryData;
 | |
| 
 | |
|       Status = GetFileNameFromFid (FoundFile.FileIdentifierDesc, ARRAY_SIZE (FileName), FileName);
 | |
|       if (EFI_ERROR (Status)) {
 | |
|         goto Error_Get_FileName;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Status = GetFileSize (
 | |
|                BlockIo,
 | |
|                DiskIo,
 | |
|                Volume,
 | |
|                &FoundFile,
 | |
|                &FileSize
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Error_Get_File_Size;
 | |
|     }
 | |
| 
 | |
|     Status = SetFileInfo (
 | |
|                &FoundFile,
 | |
|                FileSize,
 | |
|                FileName,
 | |
|                BufferSize,
 | |
|                Buffer
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Error_Set_File_Info;
 | |
|     }
 | |
| 
 | |
|     PrivFileData->FilePosition++;
 | |
|     Status = EFI_SUCCESS;
 | |
|   } else if (IS_FID_DELETED_FILE (Parent->FileIdentifierDesc)) {
 | |
|     //
 | |
|     // Code should never reach here.
 | |
|     //
 | |
|     ASSERT (FALSE);
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| Error_Set_File_Info:
 | |
| Error_Get_File_Size:
 | |
| Error_Get_FileName:
 | |
| Error_Resolve_Symlink:
 | |
|   if (NewFileEntryData != NULL) {
 | |
|     FreePool (NewFileEntryData);
 | |
|   }
 | |
| 
 | |
| Error_Find_Fe:
 | |
|   if (NewFileIdentifierDesc != NULL) {
 | |
|     FreePool ((VOID *)NewFileIdentifierDesc);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
| Error_File_Beyond_The_Eof:
 | |
| Error_Invalid_Params:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close the file handle.
 | |
| 
 | |
|   @param  This Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS The file was closed.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfClose (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_TPL                OldTpl;
 | |
|   EFI_STATUS             Status;
 | |
|   PRIVATE_UDF_FILE_DATA  *PrivFileData;
 | |
| 
 | |
|   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Exit;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (!PrivFileData->IsRootDirectory) {
 | |
|     CleanupFileInformation (&PrivFileData->File);
 | |
| 
 | |
|     if (PrivFileData->ReadDirInfo.DirectoryData != NULL) {
 | |
|       FreePool (PrivFileData->ReadDirInfo.DirectoryData);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool ((VOID *)PrivFileData);
 | |
| 
 | |
| Exit:
 | |
|   gBS->RestoreTPL (OldTpl);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close and delete the file handle.
 | |
| 
 | |
|   @param  This                     Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The file was closed and deleted.
 | |
|   @retval EFI_WARN_DELETE_FAILURE  The handle was closed but the file was not
 | |
|                                    deleted.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfDelete (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   PRIVATE_UDF_FILE_DATA  *PrivFileData;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   (VOID)PrivFileData->FileIo.Close (This);
 | |
| 
 | |
|   return EFI_WARN_DELETE_FAILURE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Write data to a file.
 | |
| 
 | |
|   @param  This       Protocol instance pointer.
 | |
|   @param  BufferSize On input size of buffer, on output amount of data in
 | |
|                      buffer.
 | |
|   @param  Buffer     The buffer in which data to write.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was written.
 | |
|   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfWrite (
 | |
|   IN      EFI_FILE_PROTOCOL  *This,
 | |
|   IN OUT  UINTN              *BufferSize,
 | |
|   IN      VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   return EFI_UNSUPPORTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get file's current position.
 | |
| 
 | |
|   @param  This      Protocol instance pointer.
 | |
|   @param  Position  Byte position from the start of the file.
 | |
| 
 | |
|   @retval EFI_SUCCESS      Position was updated.
 | |
|   @retval EFI_UNSUPPORTED  Seek request for directories is not valid.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfGetPosition (
 | |
|   IN   EFI_FILE_PROTOCOL  *This,
 | |
|   OUT  UINT64             *Position
 | |
|   )
 | |
| {
 | |
|   PRIVATE_UDF_FILE_DATA  *PrivFileData;
 | |
| 
 | |
|   if ((This == NULL) || (Position == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   //
 | |
|   // As per UEFI spec, if the file handle is a directory, then the current file
 | |
|   // position has no meaning and the operation is not supported.
 | |
|   //
 | |
|   if (IS_FID_DIRECTORY_FILE (PrivFileData->File.FileIdentifierDesc)) {
 | |
|     return EFI_UNSUPPORTED;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // The file is not a directory. So, return its position.
 | |
|   //
 | |
|   *Position = PrivFileData->FilePosition;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set file's current position.
 | |
| 
 | |
|   @param  This      Protocol instance pointer.
 | |
|   @param  Position  Byte position from the start of the file.
 | |
| 
 | |
|   @retval EFI_SUCCESS      Position was updated.
 | |
|   @retval EFI_UNSUPPORTED  Seek request for non-zero is not valid on open.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfSetPosition (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN UINT64             Position
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                      Status;
 | |
|   PRIVATE_UDF_FILE_DATA           *PrivFileData;
 | |
|   UDF_FILE_IDENTIFIER_DESCRIPTOR  *FileIdentifierDesc;
 | |
| 
 | |
|   if (This == NULL) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_UNSUPPORTED;
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   FileIdentifierDesc = _FILE (PrivFileData)->FileIdentifierDesc;
 | |
|   ASSERT (FileIdentifierDesc != NULL);
 | |
|   if (IS_FID_DIRECTORY_FILE (FileIdentifierDesc)) {
 | |
|     //
 | |
|     // If the file handle is a directory, the _only_ position that may be set is
 | |
|     // zero. This has no effect of starting the read proccess of the directory
 | |
|     // entries over.
 | |
|     //
 | |
|     if (Position == 0) {
 | |
|       PrivFileData->FilePosition          = Position;
 | |
|       PrivFileData->ReadDirInfo.FidOffset = 0;
 | |
|       Status                              = EFI_SUCCESS;
 | |
|     }
 | |
|   } else if (IS_FID_NORMAL_FILE (FileIdentifierDesc)) {
 | |
|     //
 | |
|     // Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be
 | |
|     // set to the EOF.
 | |
|     //
 | |
|     if (Position == 0xFFFFFFFFFFFFFFFF) {
 | |
|       PrivFileData->FilePosition = PrivFileData->FileSize;
 | |
|     } else {
 | |
|       PrivFileData->FilePosition = Position;
 | |
|     }
 | |
| 
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get information about a file.
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  InformationType Type of information to return in Buffer.
 | |
|   @param  BufferSize      On input size of buffer, on output amount of data in
 | |
|                           buffer.
 | |
|   @param  Buffer          The buffer to return data.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was returned.
 | |
|   @retval EFI_UNSUPPORTED      InformationType is not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in
 | |
|                                BufferSize.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfGetInfo (
 | |
|   IN      EFI_FILE_PROTOCOL  *This,
 | |
|   IN      EFI_GUID           *InformationType,
 | |
|   IN OUT  UINTN              *BufferSize,
 | |
|   OUT     VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                    Status;
 | |
|   PRIVATE_UDF_FILE_DATA         *PrivFileData;
 | |
|   PRIVATE_UDF_SIMPLE_FS_DATA    *PrivFsData;
 | |
|   EFI_FILE_SYSTEM_INFO          *FileSystemInfo;
 | |
|   UINTN                         FileSystemInfoLength;
 | |
|   UINT64                        VolumeSize;
 | |
|   UINT64                        FreeSpaceSize;
 | |
|   EFI_FILE_SYSTEM_VOLUME_LABEL  *FileSystemVolumeLabel;
 | |
|   UINTN                         FileSystemVolumeLabelLength;
 | |
|   CHAR16                        VolumeLabel[64];
 | |
| 
 | |
|   if ((This == NULL) || (InformationType == NULL) || (BufferSize == NULL) ||
 | |
|       ((*BufferSize != 0) && (Buffer == NULL)))
 | |
|   {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PrivFileData = PRIVATE_UDF_FILE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   PrivFsData = PRIVATE_UDF_SIMPLE_FS_DATA_FROM_THIS (PrivFileData->SimpleFs);
 | |
| 
 | |
|   Status = EFI_UNSUPPORTED;
 | |
| 
 | |
|   if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
 | |
|     Status = SetFileInfo (
 | |
|                _FILE (PrivFileData),
 | |
|                PrivFileData->FileSize,
 | |
|                PrivFileData->FileName,
 | |
|                BufferSize,
 | |
|                Buffer
 | |
|                );
 | |
|   } else if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
 | |
|     Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     FileSystemInfoLength = StrSize (VolumeLabel) +
 | |
|                            sizeof (EFI_FILE_SYSTEM_INFO);
 | |
|     if (*BufferSize < FileSystemInfoLength) {
 | |
|       *BufferSize = FileSystemInfoLength;
 | |
|       return EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
| 
 | |
|     FileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
 | |
|     StrCpyS (
 | |
|       FileSystemInfo->VolumeLabel,
 | |
|       (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),
 | |
|       VolumeLabel
 | |
|       );
 | |
|     Status = GetVolumeSize (
 | |
|                PrivFsData->BlockIo,
 | |
|                PrivFsData->DiskIo,
 | |
|                &PrivFsData->Volume,
 | |
|                &VolumeSize,
 | |
|                &FreeSpaceSize
 | |
|                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     FileSystemInfo->Size      = FileSystemInfoLength;
 | |
|     FileSystemInfo->ReadOnly  = TRUE;
 | |
|     FileSystemInfo->BlockSize =
 | |
|       PrivFsData->Volume.LogicalVolDesc.LogicalBlockSize;
 | |
|     FileSystemInfo->VolumeSize = VolumeSize;
 | |
|     FileSystemInfo->FreeSpace  = FreeSpaceSize;
 | |
| 
 | |
|     *BufferSize = FileSystemInfoLength;
 | |
|     Status      = EFI_SUCCESS;
 | |
|   } else if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | |
|     Status = GetVolumeLabel (&PrivFsData->Volume, ARRAY_SIZE (VolumeLabel), VolumeLabel);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     FileSystemVolumeLabelLength = StrSize (VolumeLabel) +
 | |
|                                   sizeof (EFI_FILE_SYSTEM_VOLUME_LABEL);
 | |
|     if (*BufferSize < FileSystemVolumeLabelLength) {
 | |
|       *BufferSize = FileSystemVolumeLabelLength;
 | |
|       return EFI_BUFFER_TOO_SMALL;
 | |
|     }
 | |
| 
 | |
|     FileSystemVolumeLabel = (EFI_FILE_SYSTEM_VOLUME_LABEL *)Buffer;
 | |
|     StrCpyS (
 | |
|       FileSystemVolumeLabel->VolumeLabel,
 | |
|       (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL) / sizeof (CHAR16),
 | |
|       VolumeLabel
 | |
|       );
 | |
|     Status = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set information about a file.
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  InformationType Type of information in Buffer.
 | |
|   @param  BufferSize      Size of buffer.
 | |
|   @param  Buffer          The data to write.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was set.
 | |
|   @retval EFI_UNSUPPORTED      InformationType is not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfSetInfo (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID           *InformationType,
 | |
|   IN UINTN              BufferSize,
 | |
|   IN VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   return EFI_WRITE_PROTECTED;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Flush data back for the file handle.
 | |
| 
 | |
|   @param  This Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was flushed.
 | |
|   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| UdfFlush (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   return EFI_WRITE_PROTECTED;
 | |
| }
 |