summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/alignment.h8
-rw-r--r--src/common/lz4_compression.cpp2
-rw-r--r--src/common/lz4_compression.h2
-rw-r--r--src/core/file_sys/card_image.cpp4
-rw-r--r--src/core/file_sys/content_archive.cpp9
-rw-r--r--src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp3
-rw-r--r--src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h16
-rw-r--r--src/core/file_sys/fssystem/fssystem_aes_ctr_storage.h12
-rw-r--r--src/core/file_sys/fssystem/fssystem_aes_xts_storage.h16
-rw-r--r--src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h8
-rw-r--r--src/core/file_sys/fssystem/fssystem_bucket_tree.cpp4
-rw-r--r--src/core/file_sys/fssystem/fssystem_bucket_tree.h151
-rw-r--r--src/core/file_sys/fssystem/fssystem_compressed_storage.h39
-rw-r--r--src/core/file_sys/fssystem/fssystem_compression_configuration.cpp14
-rw-r--r--src/core/file_sys/fssystem/fssystem_compression_configuration.h2
-rw-r--r--src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp8
-rw-r--r--src/core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h46
-rw-r--r--src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h18
-rw-r--r--src/core/file_sys/fssystem/fssystem_indirect_storage.cpp3
-rw-r--r--src/core/file_sys/fssystem/fssystem_indirect_storage.h88
-rw-r--r--src/core/file_sys/fssystem/fssystem_integrity_romfs_storage.h10
-rw-r--r--src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp2
-rw-r--r--src/core/file_sys/fssystem/fssystem_integrity_verification_storage.h20
-rw-r--r--src/core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h13
-rw-r--r--src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp2
-rw-r--r--src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h54
-rw-r--r--src/core/file_sys/fssystem/fssystem_nca_reader.cpp59
-rw-r--r--src/core/file_sys/fssystem/fssystem_pooled_buffer.h41
-rw-r--r--src/core/file_sys/fssystem/fssystem_sparse_storage.cpp1
-rw-r--r--src/core/file_sys/fssystem/fssystem_sparse_storage.h7
-rw-r--r--src/core/file_sys/fssystem/fssystem_switch_storage.h10
-rw-r--r--src/core/file_sys/fssystem/fssystem_utility.cpp3
-rw-r--r--src/core/file_sys/submission_package.cpp6
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp4
34 files changed, 345 insertions, 340 deletions
diff --git a/src/common/alignment.h b/src/common/alignment.h
index 0057052af..fc5c26898 100644
--- a/src/common/alignment.h
+++ b/src/common/alignment.h
@@ -12,7 +12,9 @@ namespace Common {
12 12
13template <typename T> 13template <typename T>
14 requires std::is_integral_v<T> 14 requires std::is_integral_v<T>
15[[nodiscard]] constexpr T AlignUp(T value, size_t size) { 15[[nodiscard]] constexpr T AlignUp(T value_, size_t size) {
16 using U = typename std::make_unsigned_t<T>;
17 auto value{static_cast<U>(value_)};
16 auto mod{static_cast<T>(value % size)}; 18 auto mod{static_cast<T>(value % size)};
17 value -= mod; 19 value -= mod;
18 return static_cast<T>(mod == T{0} ? value : value + size); 20 return static_cast<T>(mod == T{0} ? value : value + size);
@@ -26,7 +28,9 @@ template <typename T>
26 28
27template <typename T> 29template <typename T>
28 requires std::is_integral_v<T> 30 requires std::is_integral_v<T>
29[[nodiscard]] constexpr T AlignDown(T value, size_t size) { 31[[nodiscard]] constexpr T AlignDown(T value_, size_t size) {
32 using U = typename std::make_unsigned_t<T>;
33 const auto value{static_cast<U>(value_)};
30 return static_cast<T>(value - value % size); 34 return static_cast<T>(value - value % size);
31} 35}
32 36
diff --git a/src/common/lz4_compression.cpp b/src/common/lz4_compression.cpp
index 6867c03c4..d85ab1742 100644
--- a/src/common/lz4_compression.cpp
+++ b/src/common/lz4_compression.cpp
@@ -71,7 +71,7 @@ std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, std::size_t un
71 return uncompressed; 71 return uncompressed;
72} 72}
73 73
74int DecompressLZ4(void* dst, size_t dst_size, const void* src, size_t src_size) { 74int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size) {
75 // This is just a thin wrapper around LZ4. 75 // This is just a thin wrapper around LZ4.
76 return LZ4_decompress_safe(reinterpret_cast<const char*>(src), reinterpret_cast<char*>(dst), 76 return LZ4_decompress_safe(reinterpret_cast<const char*>(src), reinterpret_cast<char*>(dst),
77 static_cast<int>(src_size), static_cast<int>(dst_size)); 77 static_cast<int>(src_size), static_cast<int>(dst_size));
diff --git a/src/common/lz4_compression.h b/src/common/lz4_compression.h
index 7200e0f22..3ae17c2bb 100644
--- a/src/common/lz4_compression.h
+++ b/src/common/lz4_compression.h
@@ -56,6 +56,6 @@ namespace Common::Compression {
56[[nodiscard]] std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, 56[[nodiscard]] std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed,
57 std::size_t uncompressed_size); 57 std::size_t uncompressed_size);
58 58
59int DecompressLZ4(void* dst, size_t dst_size, const void* src, size_t src_size); 59[[nodiscard]] int DecompressDataLZ4(void* dst, size_t dst_size, const void* src, size_t src_size);
60 60
61} // namespace Common::Compression 61} // namespace Common::Compression
diff --git a/src/core/file_sys/card_image.cpp b/src/core/file_sys/card_image.cpp
index 54b53d020..4920905a6 100644
--- a/src/core/file_sys/card_image.cpp
+++ b/src/core/file_sys/card_image.cpp
@@ -29,8 +29,8 @@ constexpr std::array partition_names{
29 29
30XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index) 30XCI::XCI(VirtualFile file_, u64 program_id, size_t program_index)
31 : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA}, 31 : file(std::move(file_)), program_nca_status{Loader::ResultStatus::ErrorXCIMissingProgramNCA},
32 partitions(partition_names.size()), partitions_raw(partition_names.size()), 32 partitions(partition_names.size()),
33 keys{Core::Crypto::KeyManager::Instance()} { 33 partitions_raw(partition_names.size()), keys{Core::Crypto::KeyManager::Instance()} {
34 if (file->ReadObject(&header) != sizeof(GamecardHeader)) { 34 if (file->ReadObject(&header) != sizeof(GamecardHeader)) {
35 status = Loader::ResultStatus::ErrorBadXCIHeader; 35 status = Loader::ResultStatus::ErrorBadXCIHeader;
36 return; 36 return;
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index 2361b169e..44e6852fe 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -31,7 +31,7 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
31 31
32 reader = std::make_shared<NcaReader>(); 32 reader = std::make_shared<NcaReader>();
33 if (Result rc = 33 if (Result rc =
34 reader->Initialize(file, GetCryptoConfiguration(), *GetNcaCompressionConfiguration()); 34 reader->Initialize(file, GetCryptoConfiguration(), GetNcaCompressionConfiguration());
35 R_FAILED(rc)) { 35 R_FAILED(rc)) {
36 if (rc != ResultInvalidNcaSignature) { 36 if (rc != ResultInvalidNcaSignature) {
37 LOG_ERROR(Loader, "File reader errored out during header read: {:#x}", 37 LOG_ERROR(Loader, "File reader errored out during header read: {:#x}",
@@ -102,7 +102,6 @@ NCA::NCA(VirtualFile file_, const NCA* base_nca)
102 } 102 }
103 } 103 }
104 104
105 // TODO: Is this correct??
106 if (header_reader.GetEncryptionType() == NcaFsHeader::EncryptionType::AesCtrEx) { 105 if (header_reader.GetEncryptionType() == NcaFsHeader::EncryptionType::AesCtrEx) {
107 is_update = true; 106 is_update = true;
108 } 107 }
@@ -144,16 +143,14 @@ VirtualDir NCA::GetParentDirectory() const {
144} 143}
145 144
146NCAContentType NCA::GetType() const { 145NCAContentType NCA::GetType() const {
147 u8 type = static_cast<u8>(reader->GetContentType()); 146 return static_cast<NCAContentType>(reader->GetContentType());
148 return static_cast<NCAContentType>(type);
149} 147}
150 148
151u64 NCA::GetTitleId() const { 149u64 NCA::GetTitleId() const {
152 if (is_update) { 150 if (is_update) {
153 return reader->GetProgramId() | 0x800; 151 return reader->GetProgramId() | 0x800;
154 } else {
155 return reader->GetProgramId();
156 } 152 }
153 return reader->GetProgramId();
157} 154}
158 155
159RightsId NCA::GetRightsId() const { 156RightsId NCA::GetRightsId() const {
diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
index bf189c606..f25c95472 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.cpp
@@ -126,7 +126,7 @@ Result AesCtrCounterExtendedStorage::GetEntryList(Entry* out_entries, s32* out_e
126 126
127 auto cur_entry = *visitor.Get<Entry>(); 127 auto cur_entry = *visitor.Get<Entry>();
128 while (cur_entry.GetOffset() < end_offset) { 128 while (cur_entry.GetOffset() < end_offset) {
129 // Try to write the entry to the out list 129 // Try to write the entry to the out list.
130 if (entry_count != 0) { 130 if (entry_count != 0) {
131 if (count >= entry_count) { 131 if (count >= entry_count) {
132 break; 132 break;
@@ -152,7 +152,6 @@ Result AesCtrCounterExtendedStorage::GetEntryList(Entry* out_entries, s32* out_e
152 152
153size_t AesCtrCounterExtendedStorage::Read(u8* buffer, size_t size, size_t offset) const { 153size_t AesCtrCounterExtendedStorage::Read(u8* buffer, size_t size, size_t offset) const {
154 // Validate preconditions. 154 // Validate preconditions.
155 ASSERT(offset >= 0);
156 ASSERT(this->IsInitialized()); 155 ASSERT(this->IsInitialized());
157 156
158 // Allow zero size. 157 // Allow zero size.
diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
index a79904fad..d0e9ceed0 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_counter_extended_storage.h
@@ -70,14 +70,6 @@ public:
70 70
71 static Result CreateSoftwareDecryptor(std::unique_ptr<IDecryptor>* out); 71 static Result CreateSoftwareDecryptor(std::unique_ptr<IDecryptor>* out);
72 72
73private:
74 mutable BucketTree m_table;
75 VirtualFile m_data_storage;
76 std::array<u8, KeySize> m_key;
77 u32 m_secure_value;
78 s64 m_counter_offset;
79 std::unique_ptr<IDecryptor> m_decryptor;
80
81public: 73public:
82 AesCtrCounterExtendedStorage() 74 AesCtrCounterExtendedStorage()
83 : m_table(), m_data_storage(), m_secure_value(), m_counter_offset(), m_decryptor() {} 75 : m_table(), m_data_storage(), m_secure_value(), m_counter_offset(), m_decryptor() {}
@@ -109,6 +101,14 @@ public:
109private: 101private:
110 Result Initialize(const void* key, size_t key_size, u32 secure_value, VirtualFile data_storage, 102 Result Initialize(const void* key, size_t key_size, u32 secure_value, VirtualFile data_storage,
111 VirtualFile table_storage); 103 VirtualFile table_storage);
104
105private:
106 mutable BucketTree m_table;
107 VirtualFile m_data_storage;
108 std::array<u8, KeySize> m_key;
109 u32 m_secure_value;
110 s64 m_counter_offset;
111 std::unique_ptr<IDecryptor> m_decryptor;
112}; 112};
113 113
114} // namespace FileSys 114} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.h b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.h
index bceb1f9ad..339e49697 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_aes_ctr_storage.h
@@ -22,12 +22,6 @@ public:
22 static constexpr size_t KeySize = 0x10; 22 static constexpr size_t KeySize = 0x10;
23 static constexpr size_t IvSize = 0x10; 23 static constexpr size_t IvSize = 0x10;
24 24
25private:
26 VirtualFile m_base_storage;
27 std::array<u8, KeySize> m_key;
28 std::array<u8, IvSize> m_iv;
29 mutable std::optional<Core::Crypto::AESCipher<Core::Crypto::Key128>> m_cipher;
30
31public: 25public:
32 static void MakeIv(void* dst, size_t dst_size, u64 upper, s64 offset); 26 static void MakeIv(void* dst, size_t dst_size, u64 upper, s64 offset);
33 27
@@ -38,6 +32,12 @@ public:
38 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override; 32 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override;
39 virtual size_t Write(const u8* buffer, size_t size, size_t offset) override; 33 virtual size_t Write(const u8* buffer, size_t size, size_t offset) override;
40 virtual size_t GetSize() const override; 34 virtual size_t GetSize() const override;
35
36private:
37 VirtualFile m_base_storage;
38 std::array<u8, KeySize> m_key;
39 std::array<u8, IvSize> m_iv;
40 mutable std::optional<Core::Crypto::AESCipher<Core::Crypto::Key128>> m_cipher;
41}; 41};
42 42
43} // namespace FileSys 43} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
index 2307a2659..f342efb57 100644
--- a/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_aes_xts_storage.h
@@ -20,14 +20,6 @@ public:
20 static constexpr size_t KeySize = 0x20; 20 static constexpr size_t KeySize = 0x20;
21 static constexpr size_t IvSize = 0x10; 21 static constexpr size_t IvSize = 0x10;
22 22
23private:
24 VirtualFile m_base_storage;
25 std::array<u8, KeySize> m_key;
26 std::array<u8, IvSize> m_iv;
27 const size_t m_block_size;
28 std::mutex m_mutex;
29 mutable std::optional<Core::Crypto::AESCipher<Core::Crypto::Key256>> m_cipher;
30
31public: 23public:
32 static void MakeAesXtsIv(void* dst, size_t dst_size, s64 offset, size_t block_size); 24 static void MakeAesXtsIv(void* dst, size_t dst_size, s64 offset, size_t block_size);
33 25
@@ -37,6 +29,14 @@ public:
37 29
38 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override; 30 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override;
39 virtual size_t GetSize() const override; 31 virtual size_t GetSize() const override;
32
33private:
34 VirtualFile m_base_storage;
35 std::array<u8, KeySize> m_key;
36 std::array<u8, IvSize> m_iv;
37 const size_t m_block_size;
38 std::mutex m_mutex;
39 mutable std::optional<Core::Crypto::AESCipher<Core::Crypto::Key256>> m_cipher;
40}; 40};
41 41
42} // namespace FileSys 42} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
index 27d34fd17..f96691d03 100644
--- a/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_alignment_matching_storage.h
@@ -34,7 +34,7 @@ public:
34 34
35 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override { 35 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override {
36 // Allocate a work buffer on stack. 36 // Allocate a work buffer on stack.
37 alignas(DataAlignMax) char work_buf[DataAlign]; 37 alignas(DataAlignMax) std::array<char, DataAlign> work_buf;
38 38
39 // Succeed if zero size. 39 // Succeed if zero size.
40 if (size == 0) { 40 if (size == 0) {
@@ -47,13 +47,13 @@ public:
47 s64 bs_size = this->GetSize(); 47 s64 bs_size = this->GetSize();
48 ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size))); 48 ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
49 49
50 return AlignmentMatchingStorageImpl::Read(m_base_storage, work_buf, sizeof(work_buf), 50 return AlignmentMatchingStorageImpl::Read(m_base_storage, work_buf.data(), work_buf.size(),
51 DataAlign, BufferAlign, offset, buffer, size); 51 DataAlign, BufferAlign, offset, buffer, size);
52 } 52 }
53 53
54 virtual size_t Write(const u8* buffer, size_t size, size_t offset) override { 54 virtual size_t Write(const u8* buffer, size_t size, size_t offset) override {
55 // Allocate a work buffer on stack. 55 // Allocate a work buffer on stack.
56 alignas(DataAlignMax) char work_buf[DataAlign]; 56 alignas(DataAlignMax) std::array<char, DataAlign> work_buf;
57 57
58 // Succeed if zero size. 58 // Succeed if zero size.
59 if (size == 0) { 59 if (size == 0) {
@@ -66,7 +66,7 @@ public:
66 s64 bs_size = this->GetSize(); 66 s64 bs_size = this->GetSize();
67 ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size))); 67 ASSERT(R_SUCCEEDED(IStorage::CheckAccessRange(offset, size, bs_size)));
68 68
69 return AlignmentMatchingStorageImpl::Write(m_base_storage, work_buf, sizeof(work_buf), 69 return AlignmentMatchingStorageImpl::Write(m_base_storage, work_buf.data(), work_buf.size(),
70 DataAlign, BufferAlign, offset, buffer, size); 70 DataAlign, BufferAlign, offset, buffer, size);
71 } 71 }
72 72
diff --git a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp b/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
index 699a366f1..af8541009 100644
--- a/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
+++ b/src/core/file_sys/fssystem/fssystem_bucket_tree.cpp
@@ -226,7 +226,7 @@ Result BucketTree::Initialize(VirtualFile node_storage, VirtualFile entry_storag
226 m_offset_cache.offsets.end_offset = end_offset; 226 m_offset_cache.offsets.end_offset = end_offset;
227 m_offset_cache.is_initialized = true; 227 m_offset_cache.is_initialized = true;
228 228
229 // Cancel guard. 229 // We succeeded.
230 R_SUCCEED(); 230 R_SUCCEED();
231} 231}
232 232
@@ -357,7 +357,7 @@ Result BucketTree::Visitor::MoveNext() {
357 357
358 entry_index = 0; 358 entry_index = 0;
359 } else { 359 } else {
360 m_entry_index = 1; 360 m_entry_index = -1;
361 } 361 }
362 362
363 // Read the new entry. 363 // Read the new entry.
diff --git a/src/core/file_sys/fssystem/fssystem_bucket_tree.h b/src/core/file_sys/fssystem/fssystem_bucket_tree.h
index 74a2f7583..46850cd48 100644
--- a/src/core/file_sys/fssystem/fssystem_bucket_tree.h
+++ b/src/core/file_sys/fssystem/fssystem_bucket_tree.h
@@ -77,11 +77,6 @@ public:
77 }; 77 };
78 78
79 class ContinuousReadingInfo { 79 class ContinuousReadingInfo {
80 private:
81 size_t m_read_size;
82 s32 m_skip_count;
83 bool m_done;
84
85 public: 80 public:
86 constexpr ContinuousReadingInfo() : m_read_size(), m_skip_count(), m_done() {} 81 constexpr ContinuousReadingInfo() : m_read_size(), m_skip_count(), m_done() {}
87 82
@@ -119,15 +114,17 @@ public:
119 constexpr bool CanDo() const { 114 constexpr bool CanDo() const {
120 return m_read_size > 0; 115 return m_read_size > 0;
121 } 116 }
117
118 private:
119 size_t m_read_size;
120 s32 m_skip_count;
121 bool m_done;
122 }; 122 };
123 123
124private: 124private:
125 class NodeBuffer { 125 class NodeBuffer {
126 YUZU_NON_COPYABLE(NodeBuffer); 126 YUZU_NON_COPYABLE(NodeBuffer);
127 127
128 private:
129 void* m_header;
130
131 public: 128 public:
132 NodeBuffer() : m_header() {} 129 NodeBuffer() : m_header() {}
133 130
@@ -187,6 +184,9 @@ private:
187 static_assert(sizeof(T) == sizeof(NodeHeader)); 184 static_assert(sizeof(T) == sizeof(NodeHeader));
188 return reinterpret_cast<T*>(m_header); 185 return reinterpret_cast<T*>(m_header);
189 } 186 }
187
188 private:
189 void* m_header;
190 }; 190 };
191 191
192private: 192private:
@@ -219,51 +219,6 @@ private:
219 } 219 }
220 220
221public: 221public:
222 static constexpr s64 QueryHeaderStorageSize() {
223 return sizeof(Header);
224 }
225
226 static constexpr s64 QueryNodeStorageSize(size_t node_size, size_t entry_size,
227 s32 entry_count) {
228 ASSERT(entry_size >= sizeof(s64));
229 ASSERT(node_size >= entry_size + sizeof(NodeHeader));
230 ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
231 ASSERT(Common::IsPowerOfTwo(node_size));
232 ASSERT(entry_count >= 0);
233
234 if (entry_count <= 0) {
235 return 0;
236 }
237 return (1 + GetNodeL2Count(node_size, entry_size, entry_count)) *
238 static_cast<s64>(node_size);
239 }
240
241 static constexpr s64 QueryEntryStorageSize(size_t node_size, size_t entry_size,
242 s32 entry_count) {
243 ASSERT(entry_size >= sizeof(s64));
244 ASSERT(node_size >= entry_size + sizeof(NodeHeader));
245 ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
246 ASSERT(Common::IsPowerOfTwo(node_size));
247 ASSERT(entry_count >= 0);
248
249 if (entry_count <= 0) {
250 return 0;
251 }
252 return GetEntrySetCount(node_size, entry_size, entry_count) * static_cast<s64>(node_size);
253 }
254
255private:
256 mutable VirtualFile m_node_storage;
257 mutable VirtualFile m_entry_storage;
258 NodeBuffer m_node_l1;
259 size_t m_node_size;
260 size_t m_entry_size;
261 s32 m_entry_count;
262 s32 m_offset_count;
263 s32 m_entry_set_count;
264 OffsetCache m_offset_cache;
265
266public:
267 BucketTree() 222 BucketTree()
268 : m_node_storage(), m_entry_storage(), m_node_l1(), m_node_size(), m_entry_size(), 223 : m_node_storage(), m_entry_storage(), m_node_l1(), m_node_size(), m_entry_size(),
269 m_entry_count(), m_offset_count(), m_entry_set_count(), m_offset_cache() {} 224 m_entry_count(), m_offset_count(), m_entry_set_count(), m_offset_cache() {}
@@ -299,6 +254,40 @@ public:
299 R_SUCCEED(); 254 R_SUCCEED();
300 } 255 }
301 256
257public:
258 static constexpr s64 QueryHeaderStorageSize() {
259 return sizeof(Header);
260 }
261
262 static constexpr s64 QueryNodeStorageSize(size_t node_size, size_t entry_size,
263 s32 entry_count) {
264 ASSERT(entry_size >= sizeof(s64));
265 ASSERT(node_size >= entry_size + sizeof(NodeHeader));
266 ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
267 ASSERT(Common::IsPowerOfTwo(node_size));
268 ASSERT(entry_count >= 0);
269
270 if (entry_count <= 0) {
271 return 0;
272 }
273 return (1 + GetNodeL2Count(node_size, entry_size, entry_count)) *
274 static_cast<s64>(node_size);
275 }
276
277 static constexpr s64 QueryEntryStorageSize(size_t node_size, size_t entry_size,
278 s32 entry_count) {
279 ASSERT(entry_size >= sizeof(s64));
280 ASSERT(node_size >= entry_size + sizeof(NodeHeader));
281 ASSERT(NodeSizeMin <= node_size && node_size <= NodeSizeMax);
282 ASSERT(Common::IsPowerOfTwo(node_size));
283 ASSERT(entry_count >= 0);
284
285 if (entry_count <= 0) {
286 return 0;
287 }
288 return GetEntrySetCount(node_size, entry_size, entry_count) * static_cast<s64>(node_size);
289 }
290
302private: 291private:
303 template <typename EntryType> 292 template <typename EntryType>
304 struct ContinuousReadingParam { 293 struct ContinuousReadingParam {
@@ -327,35 +316,23 @@ private:
327 } 316 }
328 317
329 Result EnsureOffsetCache(); 318 Result EnsureOffsetCache();
319
320private:
321 mutable VirtualFile m_node_storage;
322 mutable VirtualFile m_entry_storage;
323 NodeBuffer m_node_l1;
324 size_t m_node_size;
325 size_t m_entry_size;
326 s32 m_entry_count;
327 s32 m_offset_count;
328 s32 m_entry_set_count;
329 OffsetCache m_offset_cache;
330}; 330};
331 331
332class BucketTree::Visitor { 332class BucketTree::Visitor {
333 YUZU_NON_COPYABLE(Visitor); 333 YUZU_NON_COPYABLE(Visitor);
334 YUZU_NON_MOVEABLE(Visitor); 334 YUZU_NON_MOVEABLE(Visitor);
335 335
336private:
337 friend class BucketTree;
338
339 union EntrySetHeader {
340 NodeHeader header;
341 struct Info {
342 s32 index;
343 s32 count;
344 s64 end;
345 s64 start;
346 } info;
347 static_assert(std::is_trivial_v<Info>);
348 };
349 static_assert(std::is_trivial_v<EntrySetHeader>);
350
351private:
352 const BucketTree* m_tree;
353 BucketTree::Offsets m_offsets;
354 void* m_entry;
355 s32 m_entry_index;
356 s32 m_entry_set_count;
357 EntrySetHeader m_entry_set;
358
359public: 336public:
360 constexpr Visitor() 337 constexpr Visitor()
361 : m_tree(), m_entry(), m_entry_index(-1), m_entry_set_count(), m_entry_set{} {} 338 : m_tree(), m_entry(), m_entry_index(-1), m_entry_set_count(), m_entry_set{} {}
@@ -412,6 +389,28 @@ private:
412 Result FindEntry(s64 virtual_address, s32 entry_set_index); 389 Result FindEntry(s64 virtual_address, s32 entry_set_index);
413 Result FindEntryWithBuffer(s64 virtual_address, s32 entry_set_index, char* buffer); 390 Result FindEntryWithBuffer(s64 virtual_address, s32 entry_set_index, char* buffer);
414 Result FindEntryWithoutBuffer(s64 virtual_address, s32 entry_set_index); 391 Result FindEntryWithoutBuffer(s64 virtual_address, s32 entry_set_index);
392
393private:
394 friend class BucketTree;
395
396 union EntrySetHeader {
397 NodeHeader header;
398 struct Info {
399 s32 index;
400 s32 count;
401 s64 end;
402 s64 start;
403 } info;
404 static_assert(std::is_trivial_v<Info>);
405 };
406 static_assert(std::is_trivial_v<EntrySetHeader>);
407
408 const BucketTree* m_tree;
409 BucketTree::Offsets m_offsets;
410 void* m_entry;
411 s32 m_entry_index;
412 s32 m_entry_set_count;
413 EntrySetHeader m_entry_set;
415}; 414};
416 415
417} // namespace FileSys 416} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_compressed_storage.h b/src/core/file_sys/fssystem/fssystem_compressed_storage.h
index e407add1b..33d93938e 100644
--- a/src/core/file_sys/fssystem/fssystem_compressed_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_compressed_storage.h
@@ -50,13 +50,6 @@ private:
50 YUZU_NON_COPYABLE(CompressedStorageCore); 50 YUZU_NON_COPYABLE(CompressedStorageCore);
51 YUZU_NON_MOVEABLE(CompressedStorageCore); 51 YUZU_NON_MOVEABLE(CompressedStorageCore);
52 52
53 private:
54 size_t m_block_size_max;
55 size_t m_continuous_reading_size_max;
56 BucketTree m_table;
57 VirtualFile m_data_storage;
58 GetDecompressorFunction m_get_decompressor_function;
59
60 public: 53 public:
61 CompressedStorageCore() : m_table(), m_data_storage() {} 54 CompressedStorageCore() : m_table(), m_data_storage() {}
62 55
@@ -296,7 +289,7 @@ private:
296 ASSERT(offset >= 0); 289 ASSERT(offset >= 0);
297 ASSERT(this->IsInitialized()); 290 ASSERT(this->IsInitialized());
298 291
299 // Succeed immediately, if we hvae nothing to read. 292 // Succeed immediately, if we have nothing to read.
300 R_SUCCEED_IF(size == 0); 293 R_SUCCEED_IF(size == 0);
301 294
302 // Declare read lambda. 295 // Declare read lambda.
@@ -307,10 +300,13 @@ private:
307 u32 physical_size; 300 u32 physical_size;
308 u32 virtual_size; 301 u32 virtual_size;
309 }; 302 };
310 Entries entries[EntriesCountMax]; 303 std::array<Entries, EntriesCountMax> entries;
311 s32 entry_count = 0; 304 s32 entry_count = 0;
312 Entry prev_entry = { 305 Entry prev_entry = {
313 .virt_offset = -1, 306 .virt_offset = -1,
307 .phys_offset{},
308 .compression_type{},
309 .phys_size{},
314 }; 310 };
315 bool will_allocate_pooled_buffer = false; 311 bool will_allocate_pooled_buffer = false;
316 s64 required_access_physical_offset = 0; 312 s64 required_access_physical_offset = 0;
@@ -594,7 +590,7 @@ private:
594 } 590 }
595 required_access_physical_size += physical_size + gap_from_prev; 591 required_access_physical_size += physical_size + gap_from_prev;
596 592
597 // Create an entry. to access the data storage. 593 // Create an entry to access the data storage.
598 entries[entry_count++] = { 594 entries[entry_count++] = {
599 .compression_type = entry.compression_type, 595 .compression_type = entry.compression_type,
600 .gap_from_prev = static_cast<u32>(gap_from_prev), 596 .gap_from_prev = static_cast<u32>(gap_from_prev),
@@ -621,7 +617,7 @@ private:
621 .virtual_size = static_cast<u32>(read_size), 617 .virtual_size = static_cast<u32>(read_size),
622 }; 618 };
623 } else { 619 } else {
624 // We have no entries, we we can just perform the read. 620 // We have no entries, so we can just perform the read.
625 const Result rc = 621 const Result rc =
626 read_func(static_cast<size_t>(read_size), 622 read_func(static_cast<size_t>(read_size),
627 [&](void* dst, size_t dst_size) -> Result { 623 [&](void* dst, size_t dst_size) -> Result {
@@ -668,6 +664,13 @@ private:
668 bool IsInitialized() const { 664 bool IsInitialized() const {
669 return m_table.IsInitialized(); 665 return m_table.IsInitialized();
670 } 666 }
667
668 private:
669 size_t m_block_size_max;
670 size_t m_continuous_reading_size_max;
671 BucketTree m_table;
672 VirtualFile m_data_storage;
673 GetDecompressorFunction m_get_decompressor_function;
671 }; 674 };
672 675
673 class CacheManager { 676 class CacheManager {
@@ -687,9 +690,6 @@ private:
687 }; 690 };
688 static_assert(std::is_trivial_v<AccessRange>); 691 static_assert(std::is_trivial_v<AccessRange>);
689 692
690 private:
691 s64 m_storage_size = 0;
692
693 public: 693 public:
694 CacheManager() = default; 694 CacheManager() = default;
695 695
@@ -890,11 +890,10 @@ private:
890 890
891 R_SUCCEED(); 891 R_SUCCEED();
892 } 892 }
893 };
894 893
895private: 894 private:
896 mutable CompressedStorageCore m_core; 895 s64 m_storage_size = 0;
897 mutable CacheManager m_cache_manager; 896 };
898 897
899public: 898public:
900 CompressedStorage() = default; 899 CompressedStorage() = default;
@@ -955,6 +954,10 @@ public:
955 return 0; 954 return 0;
956 } 955 }
957 } 956 }
957
958private:
959 mutable CompressedStorageCore m_core;
960 mutable CacheManager m_cache_manager;
958}; 961};
959 962
960} // namespace FileSys 963} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_compression_configuration.cpp b/src/core/file_sys/fssystem/fssystem_compression_configuration.cpp
index 8734f84ca..ef552cefe 100644
--- a/src/core/file_sys/fssystem/fssystem_compression_configuration.cpp
+++ b/src/core/file_sys/fssystem/fssystem_compression_configuration.cpp
@@ -9,7 +9,7 @@ namespace FileSys {
9namespace { 9namespace {
10 10
11Result DecompressLz4(void* dst, size_t dst_size, const void* src, size_t src_size) { 11Result DecompressLz4(void* dst, size_t dst_size, const void* src, size_t src_size) {
12 auto result = Common::Compression::DecompressLZ4(dst, dst_size, src, src_size); 12 auto result = Common::Compression::DecompressDataLZ4(dst, dst_size, src, src_size);
13 R_UNLESS(static_cast<size_t>(result) == dst_size, ResultUnexpectedInCompressedStorageC); 13 R_UNLESS(static_cast<size_t>(result) == dst_size, ResultUnexpectedInCompressedStorageC);
14 R_SUCCEED(); 14 R_SUCCEED();
15} 15}
@@ -23,14 +23,14 @@ constexpr DecompressorFunction GetNcaDecompressorFunction(CompressionType type)
23 } 23 }
24} 24}
25 25
26constexpr NcaCompressionConfiguration g_nca_compression_configuration{
27 .get_decompressor = GetNcaDecompressorFunction,
28};
29
30} // namespace 26} // namespace
31 27
32const NcaCompressionConfiguration* GetNcaCompressionConfiguration() { 28const NcaCompressionConfiguration& GetNcaCompressionConfiguration() {
33 return std::addressof(g_nca_compression_configuration); 29 static const NcaCompressionConfiguration configuration = {
30 .get_decompressor = GetNcaDecompressorFunction,
31 };
32
33 return configuration;
34} 34}
35 35
36} // namespace FileSys 36} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_compression_configuration.h b/src/core/file_sys/fssystem/fssystem_compression_configuration.h
index b4ec4f203..ec9b48e9a 100644
--- a/src/core/file_sys/fssystem/fssystem_compression_configuration.h
+++ b/src/core/file_sys/fssystem/fssystem_compression_configuration.h
@@ -7,6 +7,6 @@
7 7
8namespace FileSys { 8namespace FileSys {
9 9
10const NcaCompressionConfiguration* GetNcaCompressionConfiguration(); 10const NcaCompressionConfiguration& GetNcaCompressionConfiguration();
11 11
12} 12}
diff --git a/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp b/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp
index 7b89d4512..a4f0cde28 100644
--- a/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp
+++ b/src/core/file_sys/fssystem/fssystem_crypto_configuration.cpp
@@ -48,7 +48,15 @@ void GenerateKey(void* dst_key, size_t dst_key_size, const void* src_key, size_t
48 48
49const NcaCryptoConfiguration& GetCryptoConfiguration() { 49const NcaCryptoConfiguration& GetCryptoConfiguration() {
50 static const NcaCryptoConfiguration configuration = { 50 static const NcaCryptoConfiguration configuration = {
51 .header_1_sign_key_moduli{},
52 .header_1_sign_key_public_exponent{},
53 .key_area_encryption_key_source{},
54 .header_encryption_key_source{},
55 .header_encrypted_encryption_keys{},
51 .generate_key = GenerateKey, 56 .generate_key = GenerateKey,
57 .verify_sign1{},
58 .is_plaintext_header_available{},
59 .is_available_sw_key{},
52 }; 60 };
53 61
54 return configuration; 62 return configuration;
diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h b/src/core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h
index 3d216e4ae..5cf697efe 100644
--- a/src/core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_hierarchical_integrity_verification_storage.h
@@ -24,7 +24,7 @@ static_assert(alignof(HierarchicalIntegrityVerificationLevelInformation) == 0x4)
24 24
25struct HierarchicalIntegrityVerificationInformation { 25struct HierarchicalIntegrityVerificationInformation {
26 u32 max_layers; 26 u32 max_layers;
27 HierarchicalIntegrityVerificationLevelInformation info[IntegrityMaxLayerCount - 1]; 27 std::array<HierarchicalIntegrityVerificationLevelInformation, IntegrityMaxLayerCount - 1> info;
28 HashSalt seed; 28 HashSalt seed;
29 29
30 s64 GetLayeredHashSize() const { 30 s64 GetLayeredHashSize() const {
@@ -52,7 +52,7 @@ static_assert(std::is_trivial_v<HierarchicalIntegrityVerificationMetaInformation
52struct HierarchicalIntegrityVerificationSizeSet { 52struct HierarchicalIntegrityVerificationSizeSet {
53 s64 control_size; 53 s64 control_size;
54 s64 master_hash_size; 54 s64 master_hash_size;
55 s64 layered_hash_sizes[IntegrityMaxLayerCount - 2]; 55 std::array<s64, IntegrityMaxLayerCount - 2> layered_hash_sizes;
56}; 56};
57static_assert(std::is_trivial_v<HierarchicalIntegrityVerificationSizeSet>); 57static_assert(std::is_trivial_v<HierarchicalIntegrityVerificationSizeSet>);
58 58
@@ -60,13 +60,6 @@ class HierarchicalIntegrityVerificationStorage : public IReadOnlyStorage {
60 YUZU_NON_COPYABLE(HierarchicalIntegrityVerificationStorage); 60 YUZU_NON_COPYABLE(HierarchicalIntegrityVerificationStorage);
61 YUZU_NON_MOVEABLE(HierarchicalIntegrityVerificationStorage); 61 YUZU_NON_MOVEABLE(HierarchicalIntegrityVerificationStorage);
62 62
63private:
64 friend struct HierarchicalIntegrityVerificationMetaInformation;
65
66protected:
67 static constexpr s64 HashSize = 256 / 8;
68 static constexpr size_t MaxLayers = IntegrityMaxLayerCount;
69
70public: 63public:
71 using GenerateRandomFunction = void (*)(void* dst, size_t size); 64 using GenerateRandomFunction = void (*)(void* dst, size_t size);
72 65
@@ -83,7 +76,7 @@ public:
83 }; 76 };
84 77
85 private: 78 private:
86 VirtualFile m_storages[DataStorage + 1]; 79 std::array<VirtualFile, DataStorage + 1> m_storages;
87 80
88 public: 81 public:
89 void SetMasterHashStorage(VirtualFile s) { 82 void SetMasterHashStorage(VirtualFile s) {
@@ -114,19 +107,6 @@ public:
114 } 107 }
115 }; 108 };
116 109
117private:
118 static GenerateRandomFunction s_generate_random;
119
120 static void SetGenerateRandomFunction(GenerateRandomFunction func) {
121 s_generate_random = func;
122 }
123
124private:
125 std::shared_ptr<IntegrityVerificationStorage> m_verify_storages[MaxLayers - 1];
126 VirtualFile m_buffer_storages[MaxLayers - 1];
127 s64 m_data_size;
128 s32 m_max_layers;
129
130public: 110public:
131 HierarchicalIntegrityVerificationStorage(); 111 HierarchicalIntegrityVerificationStorage();
132 virtual ~HierarchicalIntegrityVerificationStorage() override { 112 virtual ~HierarchicalIntegrityVerificationStorage() override {
@@ -159,6 +139,26 @@ public:
159 static constexpr s8 GetDefaultDataCacheBufferLevel(u32 max_layers) { 139 static constexpr s8 GetDefaultDataCacheBufferLevel(u32 max_layers) {
160 return static_cast<s8>(16 + max_layers - 2); 140 return static_cast<s8>(16 + max_layers - 2);
161 } 141 }
142
143protected:
144 static constexpr s64 HashSize = 256 / 8;
145 static constexpr size_t MaxLayers = IntegrityMaxLayerCount;
146
147private:
148 static GenerateRandomFunction s_generate_random;
149
150 static void SetGenerateRandomFunction(GenerateRandomFunction func) {
151 s_generate_random = func;
152 }
153
154private:
155 friend struct HierarchicalIntegrityVerificationMetaInformation;
156
157private:
158 std::array<std::shared_ptr<IntegrityVerificationStorage>, MaxLayers - 1> m_verify_storages;
159 std::array<VirtualFile, MaxLayers - 1> m_buffer_storages;
160 s64 m_data_size;
161 s32 m_max_layers;
162}; 162};
163 163
164} // namespace FileSys 164} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h
index 717ba9748..18df400af 100644
--- a/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_hierarchical_sha256_storage.h
@@ -19,15 +19,6 @@ public:
19 static constexpr s32 LayerCount = 3; 19 static constexpr s32 LayerCount = 3;
20 static constexpr size_t HashSize = 256 / 8; 20 static constexpr size_t HashSize = 256 / 8;
21 21
22private:
23 VirtualFile m_base_storage;
24 s64 m_base_storage_size;
25 char* m_hash_buffer;
26 size_t m_hash_buffer_size;
27 s32 m_hash_target_block_size;
28 s32 m_log_size_ratio;
29 std::mutex m_mutex;
30
31public: 22public:
32 HierarchicalSha256Storage() : m_mutex() {} 23 HierarchicalSha256Storage() : m_mutex() {}
33 24
@@ -39,6 +30,15 @@ public:
39 } 30 }
40 31
41 virtual size_t Read(u8* buffer, size_t length, size_t offset) const override; 32 virtual size_t Read(u8* buffer, size_t length, size_t offset) const override;
33
34private:
35 VirtualFile m_base_storage;
36 s64 m_base_storage_size;
37 char* m_hash_buffer;
38 size_t m_hash_buffer_size;
39 s32 m_hash_target_block_size;
40 s32 m_log_size_ratio;
41 std::mutex m_mutex;
42}; 42};
43 43
44} // namespace FileSys 44} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_indirect_storage.cpp b/src/core/file_sys/fssystem/fssystem_indirect_storage.cpp
index 45aa08d30..7544e70b2 100644
--- a/src/core/file_sys/fssystem/fssystem_indirect_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_indirect_storage.cpp
@@ -72,7 +72,7 @@ Result IndirectStorage::GetEntryList(Entry* out_entries, s32* out_entry_count, s
72 72
73 auto cur_entry = *visitor.Get<Entry>(); 73 auto cur_entry = *visitor.Get<Entry>();
74 while (cur_entry.GetVirtualOffset() < end_offset) { 74 while (cur_entry.GetVirtualOffset() < end_offset) {
75 // Try to write the entry to the out list 75 // Try to write the entry to the out list.
76 if (entry_count != 0) { 76 if (entry_count != 0) {
77 if (count >= entry_count) { 77 if (count >= entry_count) {
78 break; 78 break;
@@ -98,7 +98,6 @@ Result IndirectStorage::GetEntryList(Entry* out_entries, s32* out_entry_count, s
98 98
99size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const { 99size_t IndirectStorage::Read(u8* buffer, size_t size, size_t offset) const {
100 // Validate pre-conditions. 100 // Validate pre-conditions.
101 ASSERT(offset >= 0);
102 ASSERT(this->IsInitialized()); 101 ASSERT(this->IsInitialized());
103 ASSERT(buffer != nullptr); 102 ASSERT(buffer != nullptr);
104 103
diff --git a/src/core/file_sys/fssystem/fssystem_indirect_storage.h b/src/core/file_sys/fssystem/fssystem_indirect_storage.h
index 39293667b..7854335bf 100644
--- a/src/core/file_sys/fssystem/fssystem_indirect_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_indirect_storage.h
@@ -21,27 +21,27 @@ public:
21 static constexpr size_t NodeSize = 16_KiB; 21 static constexpr size_t NodeSize = 16_KiB;
22 22
23 struct Entry { 23 struct Entry {
24 u8 virt_offset[sizeof(s64)]; 24 std::array<u8, sizeof(s64)> virt_offset;
25 u8 phys_offset[sizeof(s64)]; 25 std::array<u8, sizeof(s64)> phys_offset;
26 s32 storage_index; 26 s32 storage_index;
27 27
28 void SetVirtualOffset(const s64& ofs) { 28 void SetVirtualOffset(const s64& ofs) {
29 std::memcpy(this->virt_offset, std::addressof(ofs), sizeof(s64)); 29 std::memcpy(this->virt_offset.data(), std::addressof(ofs), sizeof(s64));
30 } 30 }
31 31
32 s64 GetVirtualOffset() const { 32 s64 GetVirtualOffset() const {
33 s64 offset; 33 s64 offset;
34 std::memcpy(std::addressof(offset), this->virt_offset, sizeof(s64)); 34 std::memcpy(std::addressof(offset), this->virt_offset.data(), sizeof(s64));
35 return offset; 35 return offset;
36 } 36 }
37 37
38 void SetPhysicalOffset(const s64& ofs) { 38 void SetPhysicalOffset(const s64& ofs) {
39 std::memcpy(this->phys_offset, std::addressof(ofs), sizeof(s64)); 39 std::memcpy(this->phys_offset.data(), std::addressof(ofs), sizeof(s64));
40 } 40 }
41 41
42 s64 GetPhysicalOffset() const { 42 s64 GetPhysicalOffset() const {
43 s64 offset; 43 s64 offset;
44 std::memcpy(std::addressof(offset), this->phys_offset, sizeof(s64)); 44 std::memcpy(std::addressof(offset), this->phys_offset.data(), sizeof(s64));
45 return offset; 45 return offset;
46 } 46 }
47 }; 47 };
@@ -61,43 +61,6 @@ public:
61 }; 61 };
62 static_assert(std::is_trivial_v<EntryData>); 62 static_assert(std::is_trivial_v<EntryData>);
63 63
64private:
65 struct ContinuousReadingEntry {
66 static constexpr size_t FragmentSizeMax = 4_KiB;
67
68 IndirectStorage::Entry entry;
69
70 s64 GetVirtualOffset() const {
71 return this->entry.GetVirtualOffset();
72 }
73
74 s64 GetPhysicalOffset() const {
75 return this->entry.GetPhysicalOffset();
76 }
77
78 bool IsFragment() const {
79 return this->entry.storage_index != 0;
80 }
81 };
82 static_assert(std::is_trivial_v<ContinuousReadingEntry>);
83
84public:
85 static constexpr s64 QueryHeaderStorageSize() {
86 return BucketTree::QueryHeaderStorageSize();
87 }
88
89 static constexpr s64 QueryNodeStorageSize(s32 entry_count) {
90 return BucketTree::QueryNodeStorageSize(NodeSize, sizeof(Entry), entry_count);
91 }
92
93 static constexpr s64 QueryEntryStorageSize(s32 entry_count) {
94 return BucketTree::QueryEntryStorageSize(NodeSize, sizeof(Entry), entry_count);
95 }
96
97private:
98 mutable BucketTree m_table;
99 std::array<VirtualFile, StorageCount> m_data_storage;
100
101public: 64public:
102 IndirectStorage() : m_table(), m_data_storage() {} 65 IndirectStorage() : m_table(), m_data_storage() {}
103 virtual ~IndirectStorage() { 66 virtual ~IndirectStorage() {
@@ -131,7 +94,7 @@ public:
131 s64 size); 94 s64 size);
132 95
133 virtual size_t GetSize() const override { 96 virtual size_t GetSize() const override {
134 BucketTree::Offsets offsets; 97 BucketTree::Offsets offsets{};
135 m_table.GetOffsets(std::addressof(offsets)); 98 m_table.GetOffsets(std::addressof(offsets));
136 99
137 return offsets.end_offset; 100 return offsets.end_offset;
@@ -139,6 +102,19 @@ public:
139 102
140 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override; 103 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override;
141 104
105public:
106 static constexpr s64 QueryHeaderStorageSize() {
107 return BucketTree::QueryHeaderStorageSize();
108 }
109
110 static constexpr s64 QueryNodeStorageSize(s32 entry_count) {
111 return BucketTree::QueryNodeStorageSize(NodeSize, sizeof(Entry), entry_count);
112 }
113
114 static constexpr s64 QueryEntryStorageSize(s32 entry_count) {
115 return BucketTree::QueryEntryStorageSize(NodeSize, sizeof(Entry), entry_count);
116 }
117
142protected: 118protected:
143 BucketTree& GetEntryTable() { 119 BucketTree& GetEntryTable() {
144 return m_table; 120 return m_table;
@@ -151,6 +127,30 @@ protected:
151 127
152 template <bool ContinuousCheck, bool RangeCheck, typename F> 128 template <bool ContinuousCheck, bool RangeCheck, typename F>
153 Result OperatePerEntry(s64 offset, s64 size, F func); 129 Result OperatePerEntry(s64 offset, s64 size, F func);
130
131private:
132 struct ContinuousReadingEntry {
133 static constexpr size_t FragmentSizeMax = 4_KiB;
134
135 IndirectStorage::Entry entry;
136
137 s64 GetVirtualOffset() const {
138 return this->entry.GetVirtualOffset();
139 }
140
141 s64 GetPhysicalOffset() const {
142 return this->entry.GetPhysicalOffset();
143 }
144
145 bool IsFragment() const {
146 return this->entry.storage_index != 0;
147 }
148 };
149 static_assert(std::is_trivial_v<ContinuousReadingEntry>);
150
151private:
152 mutable BucketTree m_table;
153 std::array<VirtualFile, StorageCount> m_data_storage;
154}; 154};
155 155
156template <bool ContinuousCheck, bool RangeCheck, typename F> 156template <bool ContinuousCheck, bool RangeCheck, typename F>
diff --git a/src/core/file_sys/fssystem/fssystem_integrity_romfs_storage.h b/src/core/file_sys/fssystem/fssystem_integrity_romfs_storage.h
index b80e9a302..5f8512b2a 100644
--- a/src/core/file_sys/fssystem/fssystem_integrity_romfs_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_integrity_romfs_storage.h
@@ -13,11 +13,6 @@ constexpr inline size_t IntegrityLayerCountRomFs = 7;
13constexpr inline size_t IntegrityHashLayerBlockSize = 16_KiB; 13constexpr inline size_t IntegrityHashLayerBlockSize = 16_KiB;
14 14
15class IntegrityRomFsStorage : public IReadOnlyStorage { 15class IntegrityRomFsStorage : public IReadOnlyStorage {
16private:
17 HierarchicalIntegrityVerificationStorage m_integrity_storage;
18 Hash m_master_hash;
19 std::shared_ptr<ArrayVfsFile<sizeof(Hash)>> m_master_hash_storage;
20
21public: 16public:
22 IntegrityRomFsStorage() {} 17 IntegrityRomFsStorage() {}
23 virtual ~IntegrityRomFsStorage() override { 18 virtual ~IntegrityRomFsStorage() override {
@@ -37,6 +32,11 @@ public:
37 virtual size_t GetSize() const override { 32 virtual size_t GetSize() const override {
38 return m_integrity_storage.GetSize(); 33 return m_integrity_storage.GetSize();
39 } 34 }
35
36private:
37 HierarchicalIntegrityVerificationStorage m_integrity_storage;
38 Hash m_master_hash;
39 std::shared_ptr<ArrayVfsFile<sizeof(Hash)>> m_master_hash_storage;
40}; 40};
41 41
42} // namespace FileSys 42} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
index 0dba0c8d9..2f73abf86 100644
--- a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.cpp
@@ -8,7 +8,7 @@ namespace FileSys {
8 8
9constexpr inline u32 ILog2(u32 val) { 9constexpr inline u32 ILog2(u32 val) {
10 ASSERT(val > 0); 10 ASSERT(val > 0);
11 return ((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val)); 11 return static_cast<u32>((sizeof(u32) * 8) - 1 - std::countl_zero<u32>(val));
12} 12}
13 13
14void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size, 14void IntegrityVerificationStorage::Initialize(VirtualFile hs, VirtualFile ds, s64 verif_block_size,
diff --git a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.h b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.h
index 08515a268..09f76799d 100644
--- a/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_integrity_verification_storage.h
@@ -18,19 +18,10 @@ public:
18 static constexpr s64 HashSize = 256 / 8; 18 static constexpr s64 HashSize = 256 / 8;
19 19
20 struct BlockHash { 20 struct BlockHash {
21 u8 hash[HashSize]; 21 std::array<u8, HashSize> hash;
22 }; 22 };
23 static_assert(std::is_trivial_v<BlockHash>); 23 static_assert(std::is_trivial_v<BlockHash>);
24 24
25private:
26 VirtualFile m_hash_storage;
27 VirtualFile m_data_storage;
28 s64 m_verification_block_size;
29 s64 m_verification_block_order;
30 s64 m_upper_layer_verification_block_size;
31 s64 m_upper_layer_verification_block_order;
32 bool m_is_real_data;
33
34public: 25public:
35 IntegrityVerificationStorage() 26 IntegrityVerificationStorage()
36 : m_verification_block_size(0), m_verification_block_order(0), 27 : m_verification_block_size(0), m_verification_block_order(0),
@@ -60,6 +51,15 @@ private:
60 ASSERT(hash != nullptr); 51 ASSERT(hash != nullptr);
61 return (hash->hash[HashSize - 1] & 0x80) != 0; 52 return (hash->hash[HashSize - 1] & 0x80) != 0;
62 } 53 }
54
55private:
56 VirtualFile m_hash_storage;
57 VirtualFile m_data_storage;
58 s64 m_verification_block_size;
59 s64 m_verification_block_order;
60 s64 m_upper_layer_verification_block_size;
61 s64 m_upper_layer_verification_block_order;
62 bool m_is_real_data;
63}; 63};
64 64
65} // namespace FileSys 65} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h b/src/core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h
index 7637272d5..c07a127fb 100644
--- a/src/core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_memory_resource_buffer_hold_storage.h
@@ -1,3 +1,6 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
1#pragma once 4#pragma once
2 5
3#include "core/file_sys/fssystem/fs_i_storage.h" 6#include "core/file_sys/fssystem/fs_i_storage.h"
@@ -8,11 +11,6 @@ class MemoryResourceBufferHoldStorage : public IStorage {
8 YUZU_NON_COPYABLE(MemoryResourceBufferHoldStorage); 11 YUZU_NON_COPYABLE(MemoryResourceBufferHoldStorage);
9 YUZU_NON_MOVEABLE(MemoryResourceBufferHoldStorage); 12 YUZU_NON_MOVEABLE(MemoryResourceBufferHoldStorage);
10 13
11private:
12 VirtualFile m_storage;
13 void* m_buffer;
14 size_t m_buffer_size;
15
16public: 14public:
17 MemoryResourceBufferHoldStorage(VirtualFile storage, size_t buffer_size) 15 MemoryResourceBufferHoldStorage(VirtualFile storage, size_t buffer_size)
18 : m_storage(std::move(storage)), m_buffer(::operator new(buffer_size)), 16 : m_storage(std::move(storage)), m_buffer(::operator new(buffer_size)),
@@ -53,6 +51,11 @@ public:
53 51
54 return m_storage->Write(buffer, size, offset); 52 return m_storage->Write(buffer, size, offset);
55 } 53 }
54
55private:
56 VirtualFile m_storage;
57 void* m_buffer;
58 size_t m_buffer_size;
56}; 59};
57 60
58} // namespace FileSys 61} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp
index 450135ae0..0f5432203 100644
--- a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp
+++ b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.cpp
@@ -228,7 +228,7 @@ Result NcaFileSystemDriver::OpenStorageImpl(VirtualFile* out, NcaFsHeaderReader*
228 228
229 // Process indirect layer. 229 // Process indirect layer.
230 if (patch_info.HasIndirectTable()) { 230 if (patch_info.HasIndirectTable()) {
231 // Create the indirect meta storage 231 // Create the indirect meta storage.
232 VirtualFile indirect_storage_meta_storage = patch_meta_indirect_meta_storage; 232 VirtualFile indirect_storage_meta_storage = patch_meta_indirect_meta_storage;
233 if (indirect_storage_meta_storage == nullptr) { 233 if (indirect_storage_meta_storage == nullptr) {
234 // If we don't have a meta storage, we must not have a patch meta hash layer. 234 // If we don't have a meta storage, we must not have a patch meta hash layer.
diff --git a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h
index d317b35ac..5771a21fc 100644
--- a/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h
+++ b/src/core/file_sys/fssystem/fssystem_nca_file_system_driver.h
@@ -37,11 +37,13 @@ struct NcaCryptoConfiguration {
37 37
38 static constexpr size_t KeyGenerationMax = 32; 38 static constexpr size_t KeyGenerationMax = 32;
39 39
40 const u8* header_1_sign_key_moduli[Header1SignatureKeyGenerationMax + 1]; 40 std::array<const u8*, Header1SignatureKeyGenerationMax + 1> header_1_sign_key_moduli;
41 u8 header_1_sign_key_public_exponent[Rsa2048KeyPublicExponentSize]; 41 std::array<u8, Rsa2048KeyPublicExponentSize> header_1_sign_key_public_exponent;
42 u8 key_area_encryption_key_source[KeyAreaEncryptionKeyIndexCount][Aes128KeySize]; 42 std::array<std::array<u8, Aes128KeySize>, KeyAreaEncryptionKeyIndexCount>
43 u8 header_encryption_key_source[Aes128KeySize]; 43 key_area_encryption_key_source;
44 u8 header_encrypted_encryption_keys[HeaderEncryptionKeyCount][Aes128KeySize]; 44 std::array<u8, Aes128KeySize> header_encryption_key_source;
45 std::array<std::array<u8, Aes128KeySize>, HeaderEncryptionKeyCount>
46 header_encrypted_encryption_keys;
45 KeyGenerationFunction generate_key; 47 KeyGenerationFunction generate_key;
46 VerifySign1Function verify_sign1; 48 VerifySign1Function verify_sign1;
47 bool is_plaintext_header_available; 49 bool is_plaintext_header_available;
@@ -89,18 +91,6 @@ class NcaReader {
89 YUZU_NON_COPYABLE(NcaReader); 91 YUZU_NON_COPYABLE(NcaReader);
90 YUZU_NON_MOVEABLE(NcaReader); 92 YUZU_NON_MOVEABLE(NcaReader);
91 93
92private:
93 NcaHeader m_header;
94 u8 m_decryption_keys[NcaHeader::DecryptionKey_Count][NcaCryptoConfiguration::Aes128KeySize];
95 VirtualFile m_body_storage;
96 VirtualFile m_header_storage;
97 u8 m_external_decryption_key[NcaCryptoConfiguration::Aes128KeySize];
98 bool m_is_software_aes_prioritized;
99 bool m_is_available_sw_key;
100 NcaHeader::EncryptionType m_header_encryption_type;
101 bool m_is_header_sign1_signature_valid;
102 GetDecompressorFunction m_get_decompressor;
103
104public: 94public:
105 NcaReader(); 95 NcaReader();
106 ~NcaReader(); 96 ~NcaReader();
@@ -147,16 +137,26 @@ public:
147 bool GetHeaderSign1Valid() const; 137 bool GetHeaderSign1Valid() const;
148 138
149 void GetHeaderSign2(void* dst, size_t size) const; 139 void GetHeaderSign2(void* dst, size_t size) const;
140
141private:
142 NcaHeader m_header;
143 std::array<std::array<u8, NcaCryptoConfiguration::Aes128KeySize>,
144 NcaHeader::DecryptionKey_Count>
145 m_decryption_keys;
146 VirtualFile m_body_storage;
147 VirtualFile m_header_storage;
148 std::array<u8, NcaCryptoConfiguration::Aes128KeySize> m_external_decryption_key;
149 bool m_is_software_aes_prioritized;
150 bool m_is_available_sw_key;
151 NcaHeader::EncryptionType m_header_encryption_type;
152 bool m_is_header_sign1_signature_valid;
153 GetDecompressorFunction m_get_decompressor;
150}; 154};
151 155
152class NcaFsHeaderReader { 156class NcaFsHeaderReader {
153 YUZU_NON_COPYABLE(NcaFsHeaderReader); 157 YUZU_NON_COPYABLE(NcaFsHeaderReader);
154 YUZU_NON_MOVEABLE(NcaFsHeaderReader); 158 YUZU_NON_MOVEABLE(NcaFsHeaderReader);
155 159
156private:
157 NcaFsHeader m_data;
158 s32 m_fs_index;
159
160public: 160public:
161 NcaFsHeaderReader() : m_fs_index(-1) { 161 NcaFsHeaderReader() : m_fs_index(-1) {
162 std::memset(std::addressof(m_data), 0, sizeof(m_data)); 162 std::memset(std::addressof(m_data), 0, sizeof(m_data));
@@ -200,6 +200,10 @@ public:
200 NcaMetaDataHashDataInfo& GetSparseMetaDataHashDataInfo(); 200 NcaMetaDataHashDataInfo& GetSparseMetaDataHashDataInfo();
201 const NcaMetaDataHashDataInfo& GetSparseMetaDataHashDataInfo() const; 201 const NcaMetaDataHashDataInfo& GetSparseMetaDataHashDataInfo() const;
202 NcaFsHeader::MetaDataHashType GetSparseMetaHashType() const; 202 NcaFsHeader::MetaDataHashType GetSparseMetaHashType() const;
203
204private:
205 NcaFsHeader m_data;
206 s32 m_fs_index;
203}; 207};
204 208
205class NcaFileSystemDriver { 209class NcaFileSystemDriver {
@@ -236,10 +240,6 @@ private:
236 None = 1, 240 None = 1,
237 }; 241 };
238 242
239private:
240 std::shared_ptr<NcaReader> m_original_reader;
241 std::shared_ptr<NcaReader> m_reader;
242
243public: 243public:
244 static Result SetupFsHeaderReader(NcaFsHeaderReader* out, const NcaReader& reader, 244 static Result SetupFsHeaderReader(NcaFsHeaderReader* out, const NcaReader& reader,
245 s32 fs_index); 245 s32 fs_index);
@@ -355,6 +355,10 @@ public:
355 VirtualFile* out_meta, VirtualFile base_storage, 355 VirtualFile* out_meta, VirtualFile base_storage,
356 const NcaCompressionInfo& compression_info, 356 const NcaCompressionInfo& compression_info,
357 GetDecompressorFunction get_decompressor); 357 GetDecompressorFunction get_decompressor);
358
359private:
360 std::shared_ptr<NcaReader> m_original_reader;
361 std::shared_ptr<NcaReader> m_reader;
358}; 362};
359 363
360} // namespace FileSys 364} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_nca_reader.cpp b/src/core/file_sys/fssystem/fssystem_nca_reader.cpp
index cd4c49069..a3714ab37 100644
--- a/src/core/file_sys/fssystem/fssystem_nca_reader.cpp
+++ b/src/core/file_sys/fssystem/fssystem_nca_reader.cpp
@@ -53,24 +53,27 @@ Result NcaReader::Initialize(VirtualFile base_storage, const NcaCryptoConfigurat
53 // Generate keys for header. 53 // Generate keys for header.
54 using AesXtsStorageForNcaHeader = AesXtsStorage; 54 using AesXtsStorageForNcaHeader = AesXtsStorage;
55 55
56 constexpr const s32 HeaderKeyTypeValues[NcaCryptoConfiguration::HeaderEncryptionKeyCount] = { 56 constexpr std::array<s32, NcaCryptoConfiguration::HeaderEncryptionKeyCount>
57 static_cast<s32>(KeyType::NcaHeaderKey1), 57 HeaderKeyTypeValues = {
58 static_cast<s32>(KeyType::NcaHeaderKey2), 58 static_cast<s32>(KeyType::NcaHeaderKey1),
59 }; 59 static_cast<s32>(KeyType::NcaHeaderKey2),
60 60 };
61 u8 header_decryption_keys[NcaCryptoConfiguration::HeaderEncryptionKeyCount] 61
62 [NcaCryptoConfiguration::Aes128KeySize]; 62 std::array<std::array<u8, NcaCryptoConfiguration::Aes128KeySize>,
63 NcaCryptoConfiguration::HeaderEncryptionKeyCount>
64 header_decryption_keys;
63 for (size_t i = 0; i < NcaCryptoConfiguration::HeaderEncryptionKeyCount; i++) { 65 for (size_t i = 0; i < NcaCryptoConfiguration::HeaderEncryptionKeyCount; i++) {
64 crypto_cfg.generate_key(header_decryption_keys[i], AesXtsStorageForNcaHeader::KeySize, 66 crypto_cfg.generate_key(header_decryption_keys[i].data(),
65 crypto_cfg.header_encrypted_encryption_keys[i], 67 AesXtsStorageForNcaHeader::KeySize,
68 crypto_cfg.header_encrypted_encryption_keys[i].data(),
66 AesXtsStorageForNcaHeader::KeySize, HeaderKeyTypeValues[i]); 69 AesXtsStorageForNcaHeader::KeySize, HeaderKeyTypeValues[i]);
67 } 70 }
68 71
69 // Create the header storage. 72 // Create the header storage.
70 const u8 header_iv[AesXtsStorageForNcaHeader::IvSize] = {}; 73 std::array<u8, AesXtsStorageForNcaHeader::IvSize> header_iv = {};
71 work_header_storage = std::make_unique<AesXtsStorageForNcaHeader>( 74 work_header_storage = std::make_unique<AesXtsStorageForNcaHeader>(
72 base_storage, header_decryption_keys[0], header_decryption_keys[1], 75 base_storage, header_decryption_keys[0].data(), header_decryption_keys[1].data(),
73 AesXtsStorageForNcaHeader::KeySize, header_iv, AesXtsStorageForNcaHeader::IvSize, 76 AesXtsStorageForNcaHeader::KeySize, header_iv.data(), AesXtsStorageForNcaHeader::IvSize,
74 NcaHeader::XtsBlockSize); 77 NcaHeader::XtsBlockSize);
75 78
76 // Check that we successfully created the storage. 79 // Check that we successfully created the storage.
@@ -94,20 +97,6 @@ Result NcaReader::Initialize(VirtualFile base_storage, const NcaCryptoConfigurat
94 m_header_encryption_type = NcaHeader::EncryptionType::None; 97 m_header_encryption_type = NcaHeader::EncryptionType::None;
95 } 98 }
96 99
97 // Validate the fixed key signature.
98 if (m_header.header1_signature_key_generation >
99 NcaCryptoConfiguration::Header1SignatureKeyGenerationMax) {
100 LOG_CRITICAL(Frontend,
101 "NcaCryptoConfiguration::Header1SignatureKeyGenerationMax = {}, "
102 "m_header.header1_signature_key_generation = {}",
103 NcaCryptoConfiguration::Header1SignatureKeyGenerationMax,
104 m_header.header1_signature_key_generation);
105 }
106
107 R_UNLESS(m_header.header1_signature_key_generation <=
108 NcaCryptoConfiguration::Header1SignatureKeyGenerationMax,
109 ResultInvalidNcaHeader1SignatureKeyGeneration);
110
111 // Verify the header sign1. 100 // Verify the header sign1.
112 if (crypto_cfg.verify_sign1 != nullptr) { 101 if (crypto_cfg.verify_sign1 != nullptr) {
113 const u8* sig = m_header.header_sign_1.data(); 102 const u8* sig = m_header.header_sign_1.data();
@@ -138,31 +127,31 @@ Result NcaReader::Initialize(VirtualFile base_storage, const NcaCryptoConfigurat
138 if (std::memcmp(ZeroRightsId.data(), m_header.rights_id.data(), NcaHeader::RightsIdSize) == 0) { 127 if (std::memcmp(ZeroRightsId.data(), m_header.rights_id.data(), NcaHeader::RightsIdSize) == 0) {
139 // If we don't, then we don't have an external key, so we need to generate decryption keys. 128 // If we don't, then we don't have an external key, so we need to generate decryption keys.
140 crypto_cfg.generate_key( 129 crypto_cfg.generate_key(
141 m_decryption_keys[NcaHeader::DecryptionKey_AesCtr], Aes128KeySize, 130 m_decryption_keys[NcaHeader::DecryptionKey_AesCtr].data(), Aes128KeySize,
142 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesCtr * Aes128KeySize, 131 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesCtr * Aes128KeySize,
143 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration())); 132 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration()));
144 crypto_cfg.generate_key( 133 crypto_cfg.generate_key(
145 m_decryption_keys[NcaHeader::DecryptionKey_AesXts1], Aes128KeySize, 134 m_decryption_keys[NcaHeader::DecryptionKey_AesXts1].data(), Aes128KeySize,
146 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesXts1 * Aes128KeySize, 135 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesXts1 * Aes128KeySize,
147 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration())); 136 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration()));
148 crypto_cfg.generate_key( 137 crypto_cfg.generate_key(
149 m_decryption_keys[NcaHeader::DecryptionKey_AesXts2], Aes128KeySize, 138 m_decryption_keys[NcaHeader::DecryptionKey_AesXts2].data(), Aes128KeySize,
150 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesXts2 * Aes128KeySize, 139 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesXts2 * Aes128KeySize,
151 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration())); 140 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration()));
152 crypto_cfg.generate_key( 141 crypto_cfg.generate_key(
153 m_decryption_keys[NcaHeader::DecryptionKey_AesCtrEx], Aes128KeySize, 142 m_decryption_keys[NcaHeader::DecryptionKey_AesCtrEx].data(), Aes128KeySize,
154 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesCtrEx * Aes128KeySize, 143 m_header.encrypted_key_area.data() + NcaHeader::DecryptionKey_AesCtrEx * Aes128KeySize,
155 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration())); 144 Aes128KeySize, GetKeyTypeValue(m_header.key_index, m_header.GetProperKeyGeneration()));
156 145
157 // Copy the hardware speed emulation key. 146 // Copy the hardware speed emulation key.
158 std::memcpy(m_decryption_keys[NcaHeader::DecryptionKey_AesCtrHw], 147 std::memcpy(m_decryption_keys[NcaHeader::DecryptionKey_AesCtrHw].data(),
159 m_header.encrypted_key_area.data() + 148 m_header.encrypted_key_area.data() +
160 NcaHeader::DecryptionKey_AesCtrHw * Aes128KeySize, 149 NcaHeader::DecryptionKey_AesCtrHw * Aes128KeySize,
161 Aes128KeySize); 150 Aes128KeySize);
162 } 151 }
163 152
164 // Clear the external decryption key. 153 // Clear the external decryption key.
165 std::memset(m_external_decryption_key, 0, sizeof(m_external_decryption_key)); 154 std::memset(m_external_decryption_key.data(), 0, m_external_decryption_key.size());
166 155
167 // Set software key availability. 156 // Set software key availability.
168 m_is_available_sw_key = crypto_cfg.is_available_sw_key; 157 m_is_available_sw_key = crypto_cfg.is_available_sw_key;
@@ -304,7 +293,7 @@ void NcaReader::GetEncryptedKey(void* dst, size_t size) const {
304const void* NcaReader::GetDecryptionKey(s32 index) const { 293const void* NcaReader::GetDecryptionKey(s32 index) const {
305 ASSERT(m_body_storage != nullptr); 294 ASSERT(m_body_storage != nullptr);
306 ASSERT(0 <= index && index < NcaHeader::DecryptionKey_Count); 295 ASSERT(0 <= index && index < NcaHeader::DecryptionKey_Count);
307 return m_decryption_keys[index]; 296 return m_decryption_keys[index].data();
308} 297}
309 298
310bool NcaReader::HasValidInternalKey() const { 299bool NcaReader::HasValidInternalKey() const {
@@ -339,14 +328,14 @@ bool NcaReader::HasExternalDecryptionKey() const {
339} 328}
340 329
341const void* NcaReader::GetExternalDecryptionKey() const { 330const void* NcaReader::GetExternalDecryptionKey() const {
342 return m_external_decryption_key; 331 return m_external_decryption_key.data();
343} 332}
344 333
345void NcaReader::SetExternalDecryptionKey(const void* src, size_t size) { 334void NcaReader::SetExternalDecryptionKey(const void* src, size_t size) {
346 ASSERT(src != nullptr); 335 ASSERT(src != nullptr);
347 ASSERT(size == sizeof(m_external_decryption_key)); 336 ASSERT(size == sizeof(m_external_decryption_key));
348 337
349 std::memcpy(m_external_decryption_key, src, sizeof(m_external_decryption_key)); 338 std::memcpy(m_external_decryption_key.data(), src, sizeof(m_external_decryption_key));
350} 339}
351 340
352void NcaReader::GetRawData(void* dst, size_t dst_size) const { 341void NcaReader::GetRawData(void* dst, size_t dst_size) const {
diff --git a/src/core/file_sys/fssystem/fssystem_pooled_buffer.h b/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
index 1df3153a1..9a6adbcb5 100644
--- a/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
+++ b/src/core/file_sys/fssystem/fssystem_pooled_buffer.h
@@ -18,27 +18,6 @@ constexpr inline size_t BufferPoolWorkSize = 320;
18class PooledBuffer { 18class PooledBuffer {
19 YUZU_NON_COPYABLE(PooledBuffer); 19 YUZU_NON_COPYABLE(PooledBuffer);
20 20
21private:
22 char* m_buffer;
23 size_t m_size;
24
25private:
26 static size_t GetAllocatableSizeMaxCore(bool large);
27
28public:
29 static size_t GetAllocatableSizeMax() {
30 return GetAllocatableSizeMaxCore(false);
31 }
32 static size_t GetAllocatableParticularlyLargeSizeMax() {
33 return GetAllocatableSizeMaxCore(true);
34 }
35
36private:
37 void Swap(PooledBuffer& rhs) {
38 std::swap(m_buffer, rhs.m_buffer);
39 std::swap(m_size, rhs.m_size);
40 }
41
42public: 21public:
43 // Constructor/Destructor. 22 // Constructor/Destructor.
44 constexpr PooledBuffer() : m_buffer(), m_size() {} 23 constexpr PooledBuffer() : m_buffer(), m_size() {}
@@ -89,8 +68,28 @@ public:
89 return m_size; 68 return m_size;
90 } 69 }
91 70
71public:
72 static size_t GetAllocatableSizeMax() {
73 return GetAllocatableSizeMaxCore(false);
74 }
75 static size_t GetAllocatableParticularlyLargeSizeMax() {
76 return GetAllocatableSizeMaxCore(true);
77 }
78
79private:
80 static size_t GetAllocatableSizeMaxCore(bool large);
81
92private: 82private:
83 void Swap(PooledBuffer& rhs) {
84 std::swap(m_buffer, rhs.m_buffer);
85 std::swap(m_size, rhs.m_size);
86 }
87
93 void AllocateCore(size_t ideal_size, size_t required_size, bool large); 88 void AllocateCore(size_t ideal_size, size_t required_size, bool large);
89
90private:
91 char* m_buffer;
92 size_t m_size;
94}; 93};
95 94
96} // namespace FileSys 95} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_sparse_storage.cpp b/src/core/file_sys/fssystem/fssystem_sparse_storage.cpp
index 05e8820f7..8574a11dd 100644
--- a/src/core/file_sys/fssystem/fssystem_sparse_storage.cpp
+++ b/src/core/file_sys/fssystem/fssystem_sparse_storage.cpp
@@ -7,7 +7,6 @@ namespace FileSys {
7 7
8size_t SparseStorage::Read(u8* buffer, size_t size, size_t offset) const { 8size_t SparseStorage::Read(u8* buffer, size_t size, size_t offset) const {
9 // Validate preconditions. 9 // Validate preconditions.
10 ASSERT(offset >= 0);
11 ASSERT(this->IsInitialized()); 10 ASSERT(this->IsInitialized());
12 ASSERT(buffer != nullptr); 11 ASSERT(buffer != nullptr);
13 12
diff --git a/src/core/file_sys/fssystem/fssystem_sparse_storage.h b/src/core/file_sys/fssystem/fssystem_sparse_storage.h
index c1ade7195..6c196ec61 100644
--- a/src/core/file_sys/fssystem/fssystem_sparse_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_sparse_storage.h
@@ -22,7 +22,6 @@ private:
22 } 22 }
23 23
24 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override { 24 virtual size_t Read(u8* buffer, size_t size, size_t offset) const override {
25 ASSERT(offset >= 0);
26 ASSERT(buffer != nullptr || size == 0); 25 ASSERT(buffer != nullptr || size == 0);
27 26
28 if (size > 0) { 27 if (size > 0) {
@@ -33,9 +32,6 @@ private:
33 } 32 }
34 }; 33 };
35 34
36private:
37 VirtualFile m_zero_storage;
38
39public: 35public:
40 SparseStorage() : IndirectStorage(), m_zero_storage(std::make_shared<ZeroStorage>()) {} 36 SparseStorage() : IndirectStorage(), m_zero_storage(std::make_shared<ZeroStorage>()) {}
41 virtual ~SparseStorage() {} 37 virtual ~SparseStorage() {}
@@ -68,6 +64,9 @@ private:
68 void SetZeroStorage() { 64 void SetZeroStorage() {
69 return this->SetStorage(1, m_zero_storage, 0, std::numeric_limits<s64>::max()); 65 return this->SetStorage(1, m_zero_storage, 0, std::numeric_limits<s64>::max());
70 } 66 }
67
68private:
69 VirtualFile m_zero_storage;
71}; 70};
72 71
73} // namespace FileSys 72} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_switch_storage.h b/src/core/file_sys/fssystem/fssystem_switch_storage.h
index 140f21ab7..2b43927cb 100644
--- a/src/core/file_sys/fssystem/fssystem_switch_storage.h
+++ b/src/core/file_sys/fssystem/fssystem_switch_storage.h
@@ -17,11 +17,6 @@ public:
17 s64 size; 17 s64 size;
18 }; 18 };
19 19
20private:
21 VirtualFile m_inside_region_storage;
22 VirtualFile m_outside_region_storage;
23 Region m_region;
24
25public: 20public:
26 RegionSwitchStorage(VirtualFile&& i, VirtualFile&& o, Region r) 21 RegionSwitchStorage(VirtualFile&& i, VirtualFile&& o, Region r)
27 : m_inside_region_storage(std::move(i)), m_outside_region_storage(std::move(o)), 22 : m_inside_region_storage(std::move(i)), m_outside_region_storage(std::move(o)),
@@ -75,6 +70,11 @@ private:
75 return false; 70 return false;
76 } 71 }
77 } 72 }
73
74private:
75 VirtualFile m_inside_region_storage;
76 VirtualFile m_outside_region_storage;
77 Region m_region;
78}; 78};
79 79
80} // namespace FileSys 80} // namespace FileSys
diff --git a/src/core/file_sys/fssystem/fssystem_utility.cpp b/src/core/file_sys/fssystem/fssystem_utility.cpp
index 4dddfd75a..ceabb8ff1 100644
--- a/src/core/file_sys/fssystem/fssystem_utility.cpp
+++ b/src/core/file_sys/fssystem/fssystem_utility.cpp
@@ -1,3 +1,6 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
1#include "core/file_sys/fssystem/fssystem_utility.h" 4#include "core/file_sys/fssystem/fssystem_utility.h"
2 5
3namespace FileSys { 6namespace FileSys {
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp
index aa41c7c31..73582ad50 100644
--- a/src/core/file_sys/submission_package.cpp
+++ b/src/core/file_sys/submission_package.cpp
@@ -19,9 +19,9 @@
19namespace FileSys { 19namespace FileSys {
20 20
21NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_) 21NSP::NSP(VirtualFile file_, u64 title_id_, std::size_t program_index_)
22 : file(std::move(file_)), expected_program_id(title_id_), program_index(program_index_), 22 : file(std::move(file_)), expected_program_id(title_id_),
23 status{Loader::ResultStatus::Success}, pfs(std::make_shared<PartitionFilesystem>(file)), 23 program_index(program_index_), status{Loader::ResultStatus::Success},
24 keys{Core::Crypto::KeyManager::Instance()} { 24 pfs(std::make_shared<PartitionFilesystem>(file)), keys{Core::Crypto::KeyManager::Instance()} {
25 if (pfs->GetStatus() != Loader::ResultStatus::Success) { 25 if (pfs->GetStatus() != Loader::ResultStatus::Success) {
26 status = pfs->GetStatus(); 26 status = pfs->GetStatus();
27 return; 27 return;
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index eaaf8cdd9..6e4d26b1e 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -310,8 +310,8 @@ private:
310class IFileSystem final : public ServiceFramework<IFileSystem> { 310class IFileSystem final : public ServiceFramework<IFileSystem> {
311public: 311public:
312 explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_) 312 explicit IFileSystem(Core::System& system_, FileSys::VirtualDir backend_, SizeGetter size_)
313 : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, 313 : ServiceFramework{system_, "IFileSystem"}, backend{std::move(backend_)}, size{std::move(
314 size{std::move(size_)} { 314 size_)} {
315 static const FunctionInfo functions[] = { 315 static const FunctionInfo functions[] = {
316 {0, &IFileSystem::CreateFile, "CreateFile"}, 316 {0, &IFileSystem::CreateFile, "CreateFile"},
317 {1, &IFileSystem::DeleteFile, "DeleteFile"}, 317 {1, &IFileSystem::DeleteFile, "DeleteFile"},