/** 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; }
// 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; }