예제 #1
0
/**
  Set the size of a file.

  This is a helper function for SetFileInfo().

  @param[in]  Instance  A pointer to the description of the volume
                        the file belongs to.
  @param[in]  File      A pointer to the description of the file.
  @param[in]  NewSize   The requested new size for the file.

  @retval  EFI_SUCCESS           The size was set.
  @retval  EFI_OUT_OF_RESOURCES  An allocation needed to process the request failed.

**/
STATIC
EFI_STATUS
SetFileSize (
  IN BOOTMON_FS_INSTANCE  *Instance,
  IN BOOTMON_FS_FILE      *BootMonFsFile,
  IN UINTN                 NewSize
  )
{
  EFI_STATUS              Status;
  UINT32                  OldSize;
  LIST_ENTRY              *RegionToFlushLink;
  LIST_ENTRY              *NextRegionToFlushLink;
  BOOTMON_FS_FILE_REGION  *Region;
  EFI_FILE_PROTOCOL       *File;
  CHAR8                   *Buffer;
  UINTN                   BufferSize;
  UINT64                  StoredPosition;

  OldSize = BootMonFsFile->Info->FileSize;

  //
  // In case of file truncation, force the regions waiting for writing to
  // not overflow the new size of the file.
  //
  if (NewSize < OldSize) {
    for (RegionToFlushLink = GetFirstNode (&BootMonFsFile->RegionToFlushLink);
         !IsNull (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
         )
    {
      NextRegionToFlushLink = GetNextNode (&BootMonFsFile->RegionToFlushLink, RegionToFlushLink);
      Region = (BOOTMON_FS_FILE_REGION*)RegionToFlushLink;
      if (Region->Offset > NewSize) {
        RemoveEntryList (RegionToFlushLink);
        FreePool (Region->Buffer);
        FreePool (Region);
      } else {
        Region->Size = MIN (Region->Size, NewSize - Region->Offset);
      }
      RegionToFlushLink = NextRegionToFlushLink;
    }

  } else if (NewSize > OldSize) {
    // Increasing a file's size is potentially complicated as it may require
    // moving the image description on media. The simplest way to do it is to
    // seek past the end of the file (which is valid in UEFI) and perform a
    // Write.
    File = &BootMonFsFile->File;

    // Save position
    Status = File->GetPosition (File, &StoredPosition);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    // Set position at the end of the file
    Status = File->SetPosition (File, OldSize);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    BufferSize = NewSize - OldSize;
    Buffer = AllocateZeroPool (BufferSize);
    if (Buffer == NULL) {
      return EFI_OUT_OF_RESOURCES;
    }

    Status = File->Write (File, &BufferSize, Buffer);
    FreePool (Buffer);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    // Restore saved position
    Status = File->SetPosition (File, StoredPosition);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  BootMonFsFile->Info->FileSize = NewSize;

  return EFI_SUCCESS;
}
예제 #2
0
// Set the file's size (NB "size", not "physical size"). If the change amounts
// to an increase, simply do a write followed by a flush.
// (This is a helper function for SetFileInfo.)
STATIC
EFI_STATUS
SetFileSize (
  IN BOOTMON_FS_INSTANCE *Instance,
  IN BOOTMON_FS_FILE     *BootMonFsFile,
  IN UINTN                NewSize
  )
{
  UINT64             StoredPosition;
  EFI_STATUS         Status;
  EFI_FILE_PROTOCOL *File;
  CHAR8              Buffer;
  UINTN              BufferSize;
  UINT32             OldSize;

  OldSize = BootMonFsFile->HwDescription.Region[0].Size;

  if (OldSize == NewSize) {
    return EFI_SUCCESS;
  }

  Buffer = 0;
  BufferSize = sizeof (Buffer);

  File = &BootMonFsFile->File;

  if (!(BootMonFsFile->OpenMode & EFI_FILE_MODE_WRITE)) {
    return EFI_ACCESS_DENIED;
  }

  if (NewSize <= OldSize) {
    OldSize = NewSize;
  } else {
    // Increasing a file's size is potentially complicated as it may require
    // moving the image description on media. The simplest way to do it is to
    // seek past the end of the file (which is valid in UEFI) and perform a
    // Write.

    // Save position
    Status = File->GetPosition (File, &StoredPosition);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = File->SetPosition (File, NewSize - 1);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Status = File->Write (File, &BufferSize, &Buffer);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    // Restore saved position
    Status = File->SetPosition (File, NewSize - 1);
    if (EFI_ERROR (Status)) {
      return Status;
    }

    Status = File->Flush (File);
    if (EFI_ERROR (Status)) {
      return Status;
    }
  }
  return EFI_SUCCESS;
}