info.c

来自「Next BIOS Source code : Extensible Firmw」· C语言 代码 · 共 693 行 · 第 1/2 页

C
693
字号
/*++

Copyright (c)  1999 - 2003 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.


Module Name:

  info.c
  
Abstract:

  Routines dealing with setting/getting file/volume info

Revision History

--*/

#include "fat.h"


EFI_STATUS
FatGetVolumeInfo (
  IN FAT_VOLUME       *Vol,
  IN OUT UINTN        *BufferSize, 
  OUT VOID            *Buffer    
  );

EFI_STATUS
FatSetVolumeInfo (
  IN FAT_VOLUME       *Vol,
  IN OUT UINTN        BufferSize, 
  OUT VOID            *Buffer    
  );

EFI_STATUS
FatGetFileInfo (
  IN FAT_VOLUME       *Vol,
  IN FAT_OFILE        *OFile,
  IN OUT UINTN        *BufferSize,
  OUT VOID            *Buffer    
  )
{
  UINTN               Size, NameSize, ResultSize, Rem;
  EFI_STATUS          Status;
  EFI_FILE_INFO       *Info;

  ASSERT_VOLUME_LOCKED (Vol);

  Size = SIZE_OF_EFI_FILE_INFO;
  NameSize = EfiStrSize (OFile->FileString);
  ResultSize = Size + NameSize;

  Status = EFI_BUFFER_TOO_SMALL;
  if (*BufferSize >= ResultSize) {
    EfiZeroMem (Buffer, ResultSize);

    Status = EFI_SUCCESS;
    Info = Buffer;

    Info->Size = ResultSize;
    Info->FileSize = OFile->FileSize;
    Info->PhysicalSize = DriverLibDivU64x32(OFile->FileSize, Vol->ClusterSize, &Rem);
    Info->PhysicalSize = DriverLibMultU64x32(
                            Info->PhysicalSize, 
                            Vol->ClusterSize) + (Rem ? Vol->ClusterSize : 0
                            );
    EfiCopyMem (&Info->CreateTime, &OFile->CreateTime, sizeof(EFI_TIME));
    EfiCopyMem (&Info->ModificationTime,
                &OFile->LastModification,
                sizeof(EFI_TIME)
                );
    EfiCopyMem (&Info->LastAccessTime, &OFile->LastAccess, sizeof(EFI_TIME));
    Info->Attribute = OFile->Attributes & EFI_FILE_VALID_ATTR;

    EfiCopyMem ((CHAR8 *) Buffer + Size, OFile->FileString, NameSize);
  }

  *BufferSize = ResultSize;
  return Status;
}

EFI_STATUS
FatGetVolumeInfo (
  IN FAT_VOLUME       *Vol,
  IN OUT UINTN        *BufferSize, 
  OUT VOID            *Buffer    
  )
{
  UINTN                   Size, NameSize, ResultSize;
  CHAR16                  Name[12];
  EFI_STATUS              Status;
  EFI_FILE_SYSTEM_INFO    *Info;
  UINTN                   ClusterSize;

  Size = SIZE_OF_EFI_FILE_SYSTEM_INFO; 
  Status = FatGetVolumeEntry  (Vol,Name);
  NameSize = EfiStrSize (Name);
  ResultSize = Size + NameSize;
  ClusterSize = Vol->ClusterSize;

  //
  // If we don't have valid info, compute it now
  //
  FatComputeFreeInfo (Vol);

  Status = EFI_BUFFER_TOO_SMALL;
  if (*BufferSize >= ResultSize) {
    Status = EFI_SUCCESS;

    Info = Buffer;
    EfiZeroMem (Info, SIZE_OF_EFI_FILE_SYSTEM_INFO);
    
    Info->Size = ResultSize;
    Info->ReadOnly = Vol->BlkIo->Media->ReadOnly;
    Info->BlockSize = (UINT32) ClusterSize;
    Info->VolumeSize = DriverLibMultU64x32 (Vol->MaxCluster, ClusterSize);
    Info->FreeSpace = DriverLibMultU64x32 (Vol->FatInfoSector.FreeInfo.ClusterCount,
                                  ClusterSize
                                  );
    EfiCopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
  }    

  *BufferSize = ResultSize;
  return Status;
}

EFI_STATUS
FatGetVolumeLabelInfo (
  IN FAT_VOLUME       *Vol,
  IN OUT UINTN        *BufferSize, 
  OUT VOID            *Buffer    
  )
{
  UINTN                             Size, NameSize, ResultSize;
  CHAR16                            Name[12];
  EFI_STATUS                        Status;
  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;

  Size = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO; 
  Status = FatGetVolumeEntry  (Vol,Name);
  NameSize = EfiStrSize (Name);
  ResultSize = Size + NameSize;

  Status = EFI_BUFFER_TOO_SMALL;
  if (*BufferSize >= ResultSize) {
    Status = EFI_SUCCESS;
    Info = Buffer;
    EfiZeroMem (Info, SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO);
    EfiCopyMem ((CHAR8 *) Buffer + Size, Name, NameSize);
  }    

  *BufferSize = ResultSize;
  return Status;
}

EFI_STATUS
FatSetVolumeInfo (
  IN FAT_VOLUME       *Vol,
  IN UINTN            BufferSize, 
  IN VOID             *Buffer    
  )
{
  EFI_STATUS              Status;
  EFI_FILE_SYSTEM_INFO    *Info;

  if (Vol->ReadOnly) {
    return EFI_WRITE_PROTECTED;
  }
  Info = (EFI_FILE_SYSTEM_INFO *)Buffer;
  
  if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + 2 || Info->Size > BufferSize){
    return EFI_BAD_BUFFER_SIZE;
  }

  Status = FatSetVolumeEntry(Vol,Info->VolumeLabel);
  return Status;
}

EFI_STATUS
FatSetVolumeLabelInfo (
  IN FAT_VOLUME       *Vol,
  IN UINTN            BufferSize, 
  IN VOID             *Buffer    
  )
{
  EFI_STATUS                        Status;
  EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info;

  if (Vol->ReadOnly) {
    return EFI_WRITE_PROTECTED;
  }

  Info = (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *)Buffer;
  
  if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 2) {
    return EFI_BAD_BUFFER_SIZE;
  }

  Status = FatSetVolumeEntry(Vol,Info->VolumeLabel);
  return Status;
}

EFI_STATUS
FatSetFileInfo (
  IN FAT_VOLUME       *Vol,
  IN FAT_IFILE        *IFile, 
  IN FAT_OFILE        *OFile,
  IN UINTN            BufferSize,
  IN VOID             *Buffer    
  )
{
  EFI_FILE_INFO       *NewInfo;
  FAT_IFILE           *NewIFile, *Open;    
  FAT_OFILE           *NewOFile;
  EFI_STATUS          Status;
  BOOLEAN             Renamed;
  EFI_TIME            ZeroTime;
  EFI_LIST_ENTRY      *List;
  FAT_OFILE           *Entry;
  EFI_STATUS          SyncStatus;  
  UINT64              Position; 
  UINTN            *ZeroBufferSize;
  void             *ZeroBuffer;
  
  EfiZeroMem(&ZeroTime, sizeof(EFI_TIME));
  Renamed = FALSE;

  NewIFile = NULL;
  NewOFile = NULL;
  Entry = NULL;
  ZeroBuffer = NULL;
  ZeroBufferSize = NULL;
  //
  // Make sure there's a valid input buffer
  //

  NewInfo = Buffer;
  if (BufferSize < SIZE_OF_EFI_FILE_INFO + 2 || NewInfo->Size > BufferSize) {
    return EFI_BAD_BUFFER_SIZE;
  }

  //
  // if a zero time is specified, then the original time is preserved
  //
  
  if (!EfiCompareMem (&ZeroTime, &NewInfo->CreateTime, sizeof(EFI_TIME))) {
    EfiCopyMem (&NewInfo->CreateTime, &OFile->CreateTime, sizeof(EFI_TIME));
  }
  if (!EfiCompareMem (&ZeroTime, &NewInfo->ModificationTime, sizeof(EFI_TIME))){
    EfiCopyMem (&NewInfo->ModificationTime,
                &OFile->LastModification,
                sizeof(EFI_TIME)
                );
  }
  if (!EfiCompareMem (&ZeroTime, &NewInfo->LastAccessTime, sizeof (EFI_TIME))) {
    EfiCopyMem (&NewInfo->LastAccessTime, &OFile->LastAccess, sizeof(EFI_TIME));
  }
  
  if ((NewInfo->Attribute & ~EFI_FILE_VALID_ATTR) || 
    !FatIsValidTime(&NewInfo->CreateTime) || 
    !FatIsValidTime(&NewInfo->ModificationTime)) {

    return EFI_INVALID_PARAMETER;
  }    

  // Can not change the directory attribute bit
  if ((NewInfo->Attribute ^ OFile->Attributes) & EFI_FILE_DIRECTORY) {
    return EFI_ACCESS_DENIED;
  }

  // If this is a directory, can't change the file size
  if ((OFile->Attributes & EFI_FILE_DIRECTORY) && 
    NewInfo->FileSize != OFile->FileSize) {
    return EFI_ACCESS_DENIED;
  }

  //
  // If this is the root directory, we can't make any updates
  //

  if (!OFile->Parent) {
    return EFI_ACCESS_DENIED;
  }

  //
  // If the IFile is read-only, the only change allowed is to
  // update the attributes.
  //

  if (IFile->ReadOnly || (OFile->Attributes & EFI_FILE_READ_ONLY)) {

    //
    // If the volume is read-only, then it doesn't matter we can't update it
    //

    if (Vol->ReadOnly) {
      return EFI_WRITE_PROTECTED;
    }

    //
    // See if the caller is trying to change anything else
    //

    if (NewInfo->FileSize != OFile->FileSize ||
      EfiCompareMem(&OFile->CreateTime, &NewInfo->CreateTime, sizeof(EFI_TIME)) ||
      EfiCompareMem (&OFile->LastModification, &NewInfo->ModificationTime, sizeof(EFI_TIME)) ||
      EfiCompareMem (&OFile->LastAccess, &NewInfo->LastAccessTime, sizeof(EFI_TIME))) {

      return EFI_ACCESS_DENIED;
    }
  }
  
  //
  // Just in case, flush the current file info
  //

  Status = FatOFileFlush (OFile);
  if (EFI_ERROR(Status)) {
    goto Done;
  }

  //
  // Open the filename and see if it refers to an existing file
  //

  Status = FatOFileOpen (OFile->Parent,
                         &NewIFile,
                         NewInfo->FileName,
                         EFI_FILE_MODE_READ,
                         0
                         );
  if (!EFI_ERROR(Status)) {

    if (NewIFile->OFile != OFile) {
      // filename is to a different filename that already exists
      Status = EFI_ACCESS_DENIED;
      goto Done;
    }

  } else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?