diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_memory_storage.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_memory_storage.hpp index 9cc59e790..4049e7f93 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_memory_storage.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_memory_storage.hpp @@ -68,7 +68,7 @@ namespace ams::fs { virtual Result OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { - case OperationId::InvalidateCache: + case OperationId::Invalidate: return ResultSuccess(); case OperationId::QueryRange: R_UNLESS(dst != nullptr, fs::ResultNullptrArgument()); diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_operate_range.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_operate_range.hpp index bd3bb06ca..3d2b8a285 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_operate_range.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_operate_range.hpp @@ -18,11 +18,16 @@ namespace ams::fs { - enum class OperationId : u64 { - Clear = ::FsOperationId_Clear, - ClearSignature = ::FsOperationId_ClearSignature, - InvalidateCache = ::FsOperationId_InvalidateCache, - QueryRange = ::FsOperationId_QueryRange, + enum class OperationId : s64 { + FillZero = 0, + DestroySignature = 1, + Invalidate = 2, + QueryRange = 3, + QueryUnpreparedRange = 4, + QueryLazyLoadCompletionRate = 5, + SetLazyLoadPriority = 6, + + ReadLazyLoadFileForciblyForDebug = 10001, }; } diff --git a/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp b/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp index 9e70d3d8a..f3771423f 100644 --- a/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp +++ b/libraries/libstratosphere/include/stratosphere/fs/fs_read_only_filesystem.hpp @@ -55,7 +55,7 @@ namespace ams::fs { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { switch (op_id) { - case OperationId::InvalidateCache: + case OperationId::Invalidate: case OperationId::QueryRange: return this->base_file->OperateRange(dst, dst_size, op_id, offset, size, src, src_size); default: diff --git a/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp b/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp index 1d6bdfd13..032a60b35 100644 --- a/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp +++ b/libraries/libstratosphere/source/fs/common/fs_file_storage.cpp @@ -72,7 +72,7 @@ namespace ams::fs { Result FileStorage::OperateRange(void *dst, size_t dst_size, OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { switch (op_id) { - case OperationId::InvalidateCache: + case OperationId::Invalidate: case OperationId::QueryRange: if (size == 0) { if (op_id == OperationId::QueryRange) { diff --git a/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp b/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp index 311cc407b..ed65e9b78 100644 --- a/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fs/fs_romfs_filesystem.cpp @@ -228,7 +228,7 @@ namespace ams::fs { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { - case OperationId::InvalidateCache: + case OperationId::Invalidate: case OperationId::QueryRange: { R_UNLESS(offset >= 0, fs::ResultOutOfRange()); diff --git a/libraries/libstratosphere/source/fssrv/fssrv_filesystem_interface_adapter.cpp b/libraries/libstratosphere/source/fssrv/fssrv_filesystem_interface_adapter.cpp index 5648e79de..1a05c34e8 100644 --- a/libraries/libstratosphere/source/fssrv/fssrv_filesystem_interface_adapter.cpp +++ b/libraries/libstratosphere/source/fssrv/fssrv_filesystem_interface_adapter.cpp @@ -32,7 +32,7 @@ namespace ams::fssrv::impl { void FileInterfaceAdapter::InvalidateCache() { AMS_ABORT_UNLESS(this->parent_filesystem->IsDeepRetryEnabled()); std::scoped_lock scoped_write_lock(this->parent_filesystem->GetReadWriteLockForCacheInvalidation()); - this->base_file->OperateRange(nullptr, 0, fs::OperationId::InvalidateCache, 0, std::numeric_limits::max(), nullptr, 0); + this->base_file->OperateRange(nullptr, 0, fs::OperationId::Invalidate, 0, std::numeric_limits::max(), nullptr, 0); } Result FileInterfaceAdapter::Read(ams::sf::Out out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) { @@ -90,9 +90,24 @@ namespace ams::fssrv::impl { } Result FileInterfaceAdapter::OperateRangeWithBuffer(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 op_id, s64 offset, s64 size) { - /* TODO: Nintendo supports calling info OperateRange using the provided buffers, when op_id is 4/5/6 or a class member is set. */ - /* We should (in the future), determine what uses this, and mimic Nintendo's behavior to the extent that we can. */ - return fs::ResultPermissionDenied(); + /* Check that we have permission to perform the operation. */ + switch (static_cast(op_id)) { + using enum fs::OperationId; + case QueryUnpreparedRange: + case QueryLazyLoadCompletionRate: + case SetLazyLoadPriority: + /* Lazy load/unprepared operations are always allowed to be performed with buffer. */ + break; + default: + /* TODO: Nintendo requires that a class member here be true here, but this class member seems to always be false. */ + /* If this changes (or reverse engineering is wrong), this should be updated. */ + return fs::ResultPermissionDenied(); + } + + /* Perform the operation. */ + R_TRY(this->base_file->OperateRange(out_buf.GetPointer(), out_buf.GetSize(), static_cast(op_id), offset, size, in_buf.GetPointer(), in_buf.GetSize())); + + return ResultSuccess(); } DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr &&dir, FileSystemInterfaceAdapter *parent, util::unique_lock &&sema) diff --git a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp index a0177d1c8..65b3bc433 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp @@ -189,7 +189,7 @@ namespace ams::fssystem { Result AesCtrCounterExtendedStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { switch (op_id) { - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: { /* Validate preconditions. */ AMS_ASSERT(offset >= 0); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_bucket_tree.cpp b/libraries/libstratosphere/source/fssystem/fssystem_bucket_tree.cpp index 9888bf237..509bf9d85 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_bucket_tree.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_bucket_tree.cpp @@ -236,7 +236,7 @@ namespace ams::fssystem { { s64 storage_size; R_TRY(this->node_storage.GetSize(std::addressof(storage_size))); - R_TRY(this->node_storage.OperateRange(fs::OperationId::InvalidateCache, 0, storage_size)); + R_TRY(this->node_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size)); } /* Refresh start/end offsets. */ @@ -270,7 +270,7 @@ namespace ams::fssystem { { s64 storage_size; R_TRY(this->entry_storage.GetSize(std::addressof(storage_size))); - R_TRY(this->entry_storage.OperateRange(fs::OperationId::InvalidateCache, 0, storage_size)); + R_TRY(this->entry_storage.OperateRange(fs::OperationId::Invalidate, 0, storage_size)); } return ResultSuccess(); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp b/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp index e9c33646b..5134bdd92 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_indirect_storage.cpp @@ -120,7 +120,7 @@ namespace ams::fssystem { Result IndirectStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { switch (op_id) { - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: { if (size > 0) { /* Validate arguments. */ diff --git a/libraries/libstratosphere/source/fssystem/fssystem_nca_file_system_driver.cpp b/libraries/libstratosphere/source/fssystem/fssystem_nca_file_system_driver.cpp index c1afd1860..2c8cbfa76 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_nca_file_system_driver.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_nca_file_system_driver.cpp @@ -269,7 +269,7 @@ namespace ams::fssystem { virtual Result OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: { R_TRY(this->true_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); R_TRY(this->false_storage->OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp b/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp index 7802e59e8..1cc074278 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_partition_file_system.cpp @@ -87,7 +87,7 @@ namespace ams::fssystem { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override final { /* Validate preconditions for operation. */ switch (op_id) { - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: R_UNLESS((this->mode & fs::OpenMode_Read) != 0, fs::ResultReadNotPermitted()); R_UNLESS((this->mode & fs::OpenMode_Write) == 0, fs::ResultUnsupportedOperationInPartitionFileB()); break; diff --git a/libraries/libstratosphere/source/fssystem/fssystem_read_only_block_cache_storage.hpp b/libraries/libstratosphere/source/fssystem/fssystem_read_only_block_cache_storage.hpp index 52445c640..f46ee156d 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_read_only_block_cache_storage.hpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_read_only_block_cache_storage.hpp @@ -92,7 +92,7 @@ namespace ams::fssystem { AMS_ASSERT(util::IsAligned(size, this->block_size)); /* If invalidating cache, invalidate our blocks. */ - if (op_id == fs::OperationId::InvalidateCache) { + if (op_id == fs::OperationId::Invalidate) { R_UNLESS(offset >= 0, fs::ResultInvalidOffset()); std::scoped_lock lk(this->mutex); diff --git a/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp b/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp index 6c8873735..d338a29da 100644 --- a/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp +++ b/libraries/libstratosphere/source/fssystem/fssystem_romfs_filesystem.cpp @@ -73,7 +73,7 @@ namespace ams::fssystem { virtual Result DoOperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) override { switch (op_id) { - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: case fs::OperationId::QueryRange: { R_UNLESS(offset >= 0, fs::ResultOutOfRange()); diff --git a/libraries/libstratosphere/source/fssystem/save/fssystem_block_cache_buffered_storage.cpp b/libraries/libstratosphere/source/fssystem/save/fssystem_block_cache_buffered_storage.cpp index 225171c92..983806db1 100644 --- a/libraries/libstratosphere/source/fssystem/save/fssystem_block_cache_buffered_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/save/fssystem_block_cache_buffered_storage.cpp @@ -389,17 +389,17 @@ namespace ams::fssystem::save { AMS_ASSERT(this->data_storage != nullptr); switch (op_id) { - case fs::OperationId::Clear: + case fs::OperationId::FillZero: { R_TRY(this->ClearImpl(offset, size)); return ResultSuccess(); } - case fs::OperationId::ClearSignature: + case fs::OperationId::DestroySignature: { R_TRY(this->ClearSignatureImpl(offset, size)); return ResultSuccess(); } - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: { R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInBlockCacheBufferedStorageB()); R_TRY(this->InvalidateCacheImpl(offset, size)); @@ -531,7 +531,7 @@ namespace ams::fssystem::save { R_SUCCEED_IF(start_offset == end_offset); /* Clear the signature for the aligned range. */ - R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::Clear, start_offset, end_offset - start_offset))); + R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::FillZero, start_offset, end_offset - start_offset))); /* Set blocking buffer manager allocations. */ buffers::EnableBlockingBufferManagerAllocation(); @@ -558,7 +558,7 @@ namespace ams::fssystem::save { R_TRY(this->UpdateLastResult(this->FlushRangeCacheEntries(offset, size, true))); /* Clear the signature for the aligned range. */ - R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::ClearSignature, start_offset, end_offset - start_offset))); + R_TRY(this->UpdateLastResult(this->data_storage->OperateRange(fs::OperationId::DestroySignature, start_offset, end_offset - start_offset))); /* Set blocking buffer manager allocations. */ buffers::EnableBlockingBufferManagerAllocation(); @@ -583,7 +583,7 @@ namespace ams::fssystem::save { /* Invalidate the aligned range. */ { - Result result = this->data_storage->OperateRange(fs::OperationId::InvalidateCache, aligned_offset, aligned_size); + Result result = this->data_storage->OperateRange(fs::OperationId::Invalidate, aligned_offset, aligned_size); AMS_ASSERT(!fs::ResultBufferAllocationFailed::Includes(result)); R_TRY(result); } diff --git a/libraries/libstratosphere/source/fssystem/save/fssystem_buffered_storage.cpp b/libraries/libstratosphere/source/fssystem/save/fssystem_buffered_storage.cpp index aff6b45b3..ea41aac8a 100644 --- a/libraries/libstratosphere/source/fssystem/save/fssystem_buffered_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/save/fssystem_buffered_storage.cpp @@ -718,7 +718,7 @@ namespace ams::fssystem::save { AMS_ASSERT(this->IsInitialized()); /* Invalidate caches, if we should. */ - if (op_id == fs::OperationId::InvalidateCache) { + if (op_id == fs::OperationId::Invalidate) { SharedCache cache(this); while (cache.AcquireNextOverlappedCache(offset, size)) { cache.Invalidate(); diff --git a/libraries/libstratosphere/source/fssystem/save/fssystem_hierarchical_integrity_verification_storage.cpp b/libraries/libstratosphere/source/fssystem/save/fssystem_hierarchical_integrity_verification_storage.cpp index d4dbb1c4b..24967553e 100644 --- a/libraries/libstratosphere/source/fssystem/save/fssystem_hierarchical_integrity_verification_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/save/fssystem_hierarchical_integrity_verification_storage.cpp @@ -316,14 +316,14 @@ namespace ams::fssystem::save { Result HierarchicalIntegrityVerificationStorage::OperateRange(void *dst, size_t dst_size, fs::OperationId op_id, s64 offset, s64 size, const void *src, size_t src_size) { switch (op_id) { - case fs::OperationId::Clear: - case fs::OperationId::ClearSignature: + case fs::OperationId::FillZero: + case fs::OperationId::DestroySignature: { R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); this->is_written_for_rollback = true; return ResultSuccess(); } - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: case fs::OperationId::QueryRange: { R_TRY(this->buffer_storages[this->max_layers - 2].OperateRange(dst, dst_size, op_id, offset, size, src, src_size)); diff --git a/libraries/libstratosphere/source/fssystem/save/fssystem_integrity_verification_storage.cpp b/libraries/libstratosphere/source/fssystem/save/fssystem_integrity_verification_storage.cpp index 18003dded..9a3b6402e 100644 --- a/libraries/libstratosphere/source/fssystem/save/fssystem_integrity_verification_storage.cpp +++ b/libraries/libstratosphere/source/fssystem/save/fssystem_integrity_verification_storage.cpp @@ -256,7 +256,7 @@ namespace ams::fssystem::save { AMS_ASSERT(util::IsAligned(size, static_cast(this->verification_block_size))); switch (op_id) { - case fs::OperationId::Clear: + case fs::OperationId::FillZero: { /* Clear should only be called for save data. */ AMS_ASSERT(this->storage_type == fs::StorageType_SaveData); @@ -289,7 +289,7 @@ namespace ams::fssystem::save { return ResultSuccess(); } - case fs::OperationId::ClearSignature: + case fs::OperationId::DestroySignature: { /* Clear Signature should only be called for save data. */ AMS_ASSERT(this->storage_type == fs::StorageType_SaveData); @@ -319,7 +319,7 @@ namespace ams::fssystem::save { /* Write the cleared signature. */ return this->hash_storage.Write(sign_offset, buf.get(), sign_size); } - case fs::OperationId::InvalidateCache: + case fs::OperationId::Invalidate: { /* Only allow cache invalidation for RomFs. */ R_UNLESS(this->storage_type != fs::StorageType_SaveData, fs::ResultUnsupportedOperationInIntegrityVerificationStorageB());