mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
ams: fs accuracy fixes, bump to 1.3.2
This commit is contained in:
parent
d85875b910
commit
3545c0aac2
10 changed files with 57 additions and 31 deletions
|
@ -1,4 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
## 1.3.2
|
||||||
|
+ Support was improved for 14.0.0+.
|
||||||
|
+ `loader` was updated to reflect the latest official behaviors.
|
||||||
|
+ `ro` was updated to reflect the latest official behaviors.
|
||||||
|
+ A number of minor issues were fixed and improvements were made, including:
|
||||||
|
+ A memory leak was fixed in filesystem path management; this could cause a crash when launching games ~100 times, or when deleting/re-downloading games.
|
||||||
|
+ A bug was fixed that could cause threads to not see a newly signaled semaphore.
|
||||||
|
+ A number of minor inaccuracies were fixed in the updated FileSystem APIs.
|
||||||
|
+ General system stability improvements to enhance the user's experience.
|
||||||
## 1.3.1
|
## 1.3.1
|
||||||
+ Support was added for 14.1.0.
|
+ Support was added for 14.1.0.
|
||||||
+ A number of minor under the hood improvements to accuracy were made to better reflect latest official system module behavior, particularly around FS apis.
|
+ A number of minor under the hood improvements to accuracy were made to better reflect latest official system module behavior, particularly around FS apis.
|
||||||
|
|
|
@ -42,8 +42,14 @@ namespace ams::fssystem {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Entry {
|
struct Entry {
|
||||||
|
enum class Encryption : u8 {
|
||||||
|
Encrypted = 0,
|
||||||
|
NotEncrypted = 1,
|
||||||
|
};
|
||||||
|
|
||||||
u8 offset[sizeof(s64)];
|
u8 offset[sizeof(s64)];
|
||||||
s32 reserved;
|
Encryption encryption_value;
|
||||||
|
u8 reserved[3];
|
||||||
s32 generation;
|
s32 generation;
|
||||||
|
|
||||||
void SetOffset(s64 value) {
|
void SetOffset(s64 value) {
|
||||||
|
|
|
@ -60,8 +60,8 @@ namespace ams::fssystem {
|
||||||
constexpr IHash256GeneratorFactory() = default;
|
constexpr IHash256GeneratorFactory() = default;
|
||||||
virtual constexpr ~IHash256GeneratorFactory() { /* ... */ }
|
virtual constexpr ~IHash256GeneratorFactory() { /* ... */ }
|
||||||
|
|
||||||
std::unique_ptr<IHash256Generator> Create() {
|
Result Create(std::unique_ptr<IHash256Generator> *out) {
|
||||||
return this->DoCreate();
|
return this->DoCreate(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
void GenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) {
|
||||||
|
@ -73,11 +73,11 @@ namespace ams::fssystem {
|
||||||
return this->DoGenerateHash(dst, dst_size, src, src_size);
|
return this->DoGenerateHash(dst, dst_size, src, src_size);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
virtual std::unique_ptr<IHash256Generator> DoCreate() = 0;
|
virtual Result DoCreate(std::unique_ptr<IHash256Generator> *out) = 0;
|
||||||
virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) = 0;
|
virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ACCURATE_TO_VERSION: 13.4.0.0 */
|
/* ACCURATE_TO_VERSION: 14.3.0.0 */
|
||||||
class IHash256GeneratorFactorySelector {
|
class IHash256GeneratorFactorySelector {
|
||||||
public:
|
public:
|
||||||
constexpr IHash256GeneratorFactorySelector() = default;
|
constexpr IHash256GeneratorFactorySelector() = default;
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace ams::fssystem {
|
||||||
IntegrityVerificationStorage() : m_verification_block_size(0), m_verification_block_order(0), m_upper_layer_verification_block_size(0), m_upper_layer_verification_block_order(0), m_buffer_manager(nullptr), m_salt(util::nullopt) { /* ... */ }
|
IntegrityVerificationStorage() : m_verification_block_size(0), m_verification_block_order(0), m_upper_layer_verification_block_size(0), m_upper_layer_verification_block_order(0), m_buffer_manager(nullptr), m_salt(util::nullopt) { /* ... */ }
|
||||||
virtual ~IntegrityVerificationStorage() override { this->Finalize(); }
|
virtual ~IntegrityVerificationStorage() override { this->Finalize(); }
|
||||||
|
|
||||||
Result Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional<fs::HashSalt> &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks);
|
void Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional<fs::HashSalt> &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks);
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
virtual Result Read(s64 offset, void *buffer, size_t size) override;
|
virtual Result Read(s64 offset, void *buffer, size_t size) override;
|
||||||
|
@ -66,9 +66,8 @@ 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;
|
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;
|
||||||
using IStorage::OperateRange;
|
using IStorage::OperateRange;
|
||||||
|
|
||||||
void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size) const {
|
void CalcBlockHash(BlockHash *out, const void *buffer, std::unique_ptr<fssystem::IHash256Generator> &generator) const {
|
||||||
auto generator = m_hash_generator_factory->Create();
|
return this->CalcBlockHash(out, buffer, static_cast<size_t>(m_verification_block_size), generator);
|
||||||
return this->CalcBlockHash(out, buffer, block_size, generator);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s64 GetBlockSize() const {
|
s64 GetBlockSize() const {
|
||||||
|
@ -81,10 +80,6 @@ namespace ams::fssystem {
|
||||||
|
|
||||||
void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size, std::unique_ptr<fssystem::IHash256Generator> &generator) const;
|
void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size, std::unique_ptr<fssystem::IHash256Generator> &generator) const;
|
||||||
|
|
||||||
void CalcBlockHash(BlockHash *out, const void *buffer, std::unique_ptr<fssystem::IHash256Generator> &generator) const {
|
|
||||||
return this->CalcBlockHash(out, buffer, static_cast<size_t>(m_verification_block_size), generator);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IsCleared(bool *is_cleared, const BlockHash &hash);
|
Result IsCleared(bool *is_cleared, const BlockHash &hash);
|
||||||
private:
|
private:
|
||||||
static void SetValidationBit(BlockHash *hash) {
|
static void SetValidationBit(BlockHash *hash) {
|
||||||
|
|
|
@ -56,8 +56,12 @@ namespace ams::fssystem {
|
||||||
public:
|
public:
|
||||||
constexpr ShaHashGeneratorFactory() = default;
|
constexpr ShaHashGeneratorFactory() = default;
|
||||||
protected:
|
protected:
|
||||||
virtual std::unique_ptr<IHash256Generator> DoCreate() override {
|
virtual Result DoCreate(std::unique_ptr<IHash256Generator> *out) override {
|
||||||
return std::unique_ptr<IHash256Generator>(new ShaHashGenerator<Traits>());
|
auto generator = std::unique_ptr<IHash256Generator>(new ShaHashGenerator<Traits>());
|
||||||
|
R_UNLESS(generator != nullptr, fs::ResultAllocationMemoryFailedNew());
|
||||||
|
|
||||||
|
*out = std::move(generator);
|
||||||
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) override {
|
virtual void DoGenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) override {
|
||||||
|
|
|
@ -71,6 +71,7 @@ namespace ams::hos {
|
||||||
Version_13_2_1 = ::ams::TargetFirmware_13_2_1,
|
Version_13_2_1 = ::ams::TargetFirmware_13_2_1,
|
||||||
Version_14_0_0 = ::ams::TargetFirmware_14_0_0,
|
Version_14_0_0 = ::ams::TargetFirmware_14_0_0,
|
||||||
Version_14_1_0 = ::ams::TargetFirmware_14_1_0,
|
Version_14_1_0 = ::ams::TargetFirmware_14_1_0,
|
||||||
|
Version_14_1_1 = ::ams::TargetFirmware_14_1_1,
|
||||||
|
|
||||||
Version_Current = ::ams::TargetFirmware_Current,
|
Version_Current = ::ams::TargetFirmware_Current,
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,11 @@ namespace ams::fssystem {
|
||||||
AMS_ASSERT(decryptor != nullptr);
|
AMS_ASSERT(decryptor != nullptr);
|
||||||
|
|
||||||
/* Initialize the bucket tree table. */
|
/* Initialize the bucket tree table. */
|
||||||
R_TRY(m_table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count));
|
if (entry_count > 0) {
|
||||||
|
R_TRY(m_table.Initialize(allocator, node_storage, entry_storage, NodeSize, sizeof(Entry), entry_count));
|
||||||
|
} else {
|
||||||
|
m_table.Initialize(NodeSize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Set members. */
|
/* Set members. */
|
||||||
m_data_storage = data_storage;
|
m_data_storage = data_storage;
|
||||||
|
@ -174,15 +178,18 @@ namespace ams::fssystem {
|
||||||
const auto cur_size = static_cast<size_t>(std::min(remaining_size, data_size));
|
const auto cur_size = static_cast<size_t>(std::min(remaining_size, data_size));
|
||||||
AMS_ASSERT(cur_size <= size);
|
AMS_ASSERT(cur_size <= size);
|
||||||
|
|
||||||
/* Make the CTR for the data we're decrypting. */
|
/* If necessary, perform decryption. */
|
||||||
const auto counter_offset = m_counter_offset + cur_entry_offset + data_offset;
|
if (cur_entry.encryption_value == Entry::Encryption::Encrypted) {
|
||||||
NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast<u32>(cur_entry.generation), .secure_value = m_secure_value } };
|
/* Make the CTR for the data we're decrypting. */
|
||||||
|
const auto counter_offset = m_counter_offset + cur_entry_offset + data_offset;
|
||||||
|
NcaAesCtrUpperIv upper_iv = { .part = { .generation = static_cast<u32>(cur_entry.generation), .secure_value = m_secure_value } };
|
||||||
|
|
||||||
u8 iv[IvSize];
|
u8 iv[IvSize];
|
||||||
AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset);
|
AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset);
|
||||||
|
|
||||||
/* Decrypt. */
|
/* Decrypt. */
|
||||||
m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize);
|
m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize);
|
||||||
|
}
|
||||||
|
|
||||||
/* Advance. */
|
/* Advance. */
|
||||||
cur_data += cur_size;
|
cur_data += cur_size;
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
namespace ams::fssystem {
|
namespace ams::fssystem {
|
||||||
|
|
||||||
Result IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional<fs::HashSalt> &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks) {
|
void IntegrityVerificationStorage::Initialize(fs::SubStorage hs, fs::SubStorage ds, s64 verif_block_size, s64 upper_layer_verif_block_size, fs::IBufferManager *bm, fssystem::IHash256GeneratorFactory *hgf, const util::optional<fs::HashSalt> &salt, bool is_real_data, bool is_writable, bool allow_cleared_blocks) {
|
||||||
/* Validate preconditions. */
|
/* Validate preconditions. */
|
||||||
AMS_ASSERT(verif_block_size >= HashSize);
|
AMS_ASSERT(verif_block_size >= HashSize);
|
||||||
AMS_ASSERT(bm != nullptr);
|
AMS_ASSERT(bm != nullptr);
|
||||||
|
@ -61,7 +61,6 @@ namespace ams::fssystem {
|
||||||
m_is_real_data = is_real_data;
|
m_is_real_data = is_real_data;
|
||||||
m_is_writable = is_writable;
|
m_is_writable = is_writable;
|
||||||
m_allow_cleared_blocks = allow_cleared_blocks;
|
m_allow_cleared_blocks = allow_cleared_blocks;
|
||||||
R_SUCCEED();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrityVerificationStorage::Finalize() {
|
void IntegrityVerificationStorage::Finalize() {
|
||||||
|
@ -120,7 +119,8 @@ namespace ams::fssystem {
|
||||||
Result verify_hash_result = ResultSuccess();
|
Result verify_hash_result = ResultSuccess();
|
||||||
|
|
||||||
/* Create hash generator. */
|
/* Create hash generator. */
|
||||||
auto generator = m_hash_generator_factory->Create();
|
std::unique_ptr<IHash256Generator> generator = nullptr;
|
||||||
|
R_TRY(m_hash_generator_factory->Create(std::addressof(generator)));
|
||||||
|
|
||||||
/* Prepare to validate the signatures. */
|
/* Prepare to validate the signatures. */
|
||||||
const auto signature_count = size >> m_verification_block_order;
|
const auto signature_count = size >> m_verification_block_order;
|
||||||
|
@ -221,7 +221,9 @@ namespace ams::fssystem {
|
||||||
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
|
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), sizeof(BlockHash));
|
||||||
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
|
const auto buffer_count = std::min(signature_count, signature_buffer.GetSize() / sizeof(BlockHash));
|
||||||
|
|
||||||
auto generator = m_hash_generator_factory->Create();
|
/* Create hash generator. */
|
||||||
|
std::unique_ptr<IHash256Generator> generator = nullptr;
|
||||||
|
R_TRY(m_hash_generator_factory->Create(std::addressof(generator)));
|
||||||
|
|
||||||
while (updated_count < signature_count) {
|
while (updated_count < signature_count) {
|
||||||
const auto cur_count = std::min(buffer_count, signature_count - updated_count);
|
const auto cur_count = std::min(buffer_count, signature_count - updated_count);
|
||||||
|
@ -326,7 +328,7 @@ namespace ams::fssystem {
|
||||||
R_TRY(m_hash_storage.Read(sign_offset, buf.get(), sign_size));
|
R_TRY(m_hash_storage.Read(sign_offset, buf.get(), sign_size));
|
||||||
|
|
||||||
/* Clear the signature. */
|
/* Clear the signature. */
|
||||||
/* This sets all bytes to FF, with the verification bit cleared. */
|
/* This flips all bits other than the verification bit. */
|
||||||
for (auto i = 0; i < sign_size; ++i) {
|
for (auto i = 0; i < sign_size; ++i) {
|
||||||
buf[i] ^= ((i + 1) % HashSize == 0 ? 0x7F : 0xFF);
|
buf[i] ^= ((i + 1) % HashSize == 0 ? 0x7F : 0xFF);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@
|
||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
|
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MINOR 3
|
#define ATMOSPHERE_RELEASE_VERSION_MINOR 3
|
||||||
#define ATMOSPHERE_RELEASE_VERSION_MICRO 1
|
#define ATMOSPHERE_RELEASE_VERSION_MICRO 2
|
||||||
|
|
||||||
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
#define ATMOSPHERE_RELEASE_VERSION ATMOSPHERE_RELEASE_VERSION_MAJOR, ATMOSPHERE_RELEASE_VERSION_MINOR, ATMOSPHERE_RELEASE_VERSION_MICRO
|
||||||
|
|
||||||
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 14
|
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MAJOR 14
|
||||||
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
|
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
|
||||||
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0
|
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1
|
||||||
|
|
|
@ -69,8 +69,9 @@
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_13_2_1 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 1)
|
#define ATMOSPHERE_TARGET_FIRMWARE_13_2_1 ATMOSPHERE_TARGET_FIRMWARE(13, 2, 1)
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_14_0_0 ATMOSPHERE_TARGET_FIRMWARE(14, 0, 0)
|
#define ATMOSPHERE_TARGET_FIRMWARE_14_0_0 ATMOSPHERE_TARGET_FIRMWARE(14, 0, 0)
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_14_1_0 ATMOSPHERE_TARGET_FIRMWARE(14, 1, 0)
|
#define ATMOSPHERE_TARGET_FIRMWARE_14_1_0 ATMOSPHERE_TARGET_FIRMWARE(14, 1, 0)
|
||||||
|
#define ATMOSPHERE_TARGET_FIRMWARE_14_1_1 ATMOSPHERE_TARGET_FIRMWARE(14, 1, 1)
|
||||||
|
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_14_1_0
|
#define ATMOSPHERE_TARGET_FIRMWARE_CURRENT ATMOSPHERE_TARGET_FIRMWARE_14_1_1
|
||||||
|
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
|
#define ATMOSPHERE_TARGET_FIRMWARE_MIN ATMOSPHERE_TARGET_FIRMWARE(0, 0, 0)
|
||||||
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
|
#define ATMOSPHERE_TARGET_FIRMWARE_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
|
||||||
|
@ -132,6 +133,7 @@ namespace ams {
|
||||||
TargetFirmware_13_2_1 = ATMOSPHERE_TARGET_FIRMWARE_13_2_1,
|
TargetFirmware_13_2_1 = ATMOSPHERE_TARGET_FIRMWARE_13_2_1,
|
||||||
TargetFirmware_14_0_0 = ATMOSPHERE_TARGET_FIRMWARE_14_0_0,
|
TargetFirmware_14_0_0 = ATMOSPHERE_TARGET_FIRMWARE_14_0_0,
|
||||||
TargetFirmware_14_1_0 = ATMOSPHERE_TARGET_FIRMWARE_14_1_0,
|
TargetFirmware_14_1_0 = ATMOSPHERE_TARGET_FIRMWARE_14_1_0,
|
||||||
|
TargetFirmware_14_1_1 = ATMOSPHERE_TARGET_FIRMWARE_14_1_1,
|
||||||
|
|
||||||
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,
|
TargetFirmware_Current = ATMOSPHERE_TARGET_FIRMWARE_CURRENT,
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue