Skip to content

Commit

Permalink
ams: fs accuracy fixes, bump to 1.3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
SciresM committed Apr 29, 2022
1 parent d85875b commit 3545c0a
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 31 deletions.
9 changes: 9 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
# 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
+ 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,14 @@ namespace ams::fssystem {
};

struct Entry {
enum class Encryption : u8 {
Encrypted = 0,
NotEncrypted = 1,
};

u8 offset[sizeof(s64)];
s32 reserved;
Encryption encryption_value;
u8 reserved[3];
s32 generation;

void SetOffset(s64 value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ namespace ams::fssystem {
constexpr IHash256GeneratorFactory() = default;
virtual constexpr ~IHash256GeneratorFactory() { /* ... */ }

std::unique_ptr<IHash256Generator> Create() {
return this->DoCreate();
Result Create(std::unique_ptr<IHash256Generator> *out) {
return this->DoCreate(out);
}

void GenerateHash(void *dst, size_t dst_size, const void *src, size_t src_size) {
Expand All @@ -73,11 +73,11 @@ namespace ams::fssystem {
return this->DoGenerateHash(dst, dst_size, src, src_size);
}
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;
};

/* ACCURATE_TO_VERSION: 13.4.0.0 */
/* ACCURATE_TO_VERSION: 14.3.0.0 */
class IHash256GeneratorFactorySelector {
public:
constexpr IHash256GeneratorFactorySelector() = default;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) { /* ... */ }
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();

virtual Result Read(s64 offset, void *buffer, size_t size) override;
Expand All @@ -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;
using IStorage::OperateRange;

void CalcBlockHash(BlockHash *out, const void *buffer, size_t block_size) const {
auto generator = m_hash_generator_factory->Create();
return this->CalcBlockHash(out, buffer, block_size, generator);
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);
}

s64 GetBlockSize() const {
Expand All @@ -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, 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);
private:
static void SetValidationBit(BlockHash *hash) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,12 @@ namespace ams::fssystem {
public:
constexpr ShaHashGeneratorFactory() = default;
protected:
virtual std::unique_ptr<IHash256Generator> DoCreate() override {
return std::unique_ptr<IHash256Generator>(new ShaHashGenerator<Traits>());
virtual Result DoCreate(std::unique_ptr<IHash256Generator> *out) override {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ namespace ams::hos {
Version_13_2_1 = ::ams::TargetFirmware_13_2_1,
Version_14_0_0 = ::ams::TargetFirmware_14_0_0,
Version_14_1_0 = ::ams::TargetFirmware_14_1_0,
Version_14_1_1 = ::ams::TargetFirmware_14_1_1,

Version_Current = ::ams::TargetFirmware_Current,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,11 @@ namespace ams::fssystem {
AMS_ASSERT(decryptor != nullptr);

/* 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. */
m_data_storage = data_storage;
Expand Down Expand Up @@ -174,15 +178,18 @@ namespace ams::fssystem {
const auto cur_size = static_cast<size_t>(std::min(remaining_size, data_size));
AMS_ASSERT(cur_size <= size);

/* 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 } };
/* If necessary, perform decryption. */
if (cur_entry.encryption_value == Entry::Encryption::Encrypted) {
/* 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];
AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset);
u8 iv[IvSize];
AesCtrStorageByPointer::MakeIv(iv, IvSize, upper_iv.value, counter_offset);

/* Decrypt. */
m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize);
/* Decrypt. */
m_decryptor->Decrypt(cur_data, cur_size, m_key, KeySize, iv, IvSize);
}

/* Advance. */
cur_data += cur_size;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

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. */
AMS_ASSERT(verif_block_size >= HashSize);
AMS_ASSERT(bm != nullptr);
Expand Down Expand Up @@ -61,7 +61,6 @@ namespace ams::fssystem {
m_is_real_data = is_real_data;
m_is_writable = is_writable;
m_allow_cleared_blocks = allow_cleared_blocks;
R_SUCCEED();
}

void IntegrityVerificationStorage::Finalize() {
Expand Down Expand Up @@ -120,7 +119,8 @@ namespace ams::fssystem {
Result verify_hash_result = ResultSuccess();

/* 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. */
const auto signature_count = size >> m_verification_block_order;
Expand Down Expand Up @@ -221,7 +221,9 @@ namespace ams::fssystem {
PooledBuffer signature_buffer(signature_count * sizeof(BlockHash), 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) {
const auto cur_count = std::min(buffer_count, signature_count - updated_count);
Expand Down Expand Up @@ -326,7 +328,7 @@ namespace ams::fssystem {
R_TRY(m_hash_storage.Read(sign_offset, buf.get(), sign_size));

/* 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) {
buf[i] ^= ((i + 1) % HashSize == 0 ? 0x7F : 0xFF);
}
Expand Down
4 changes: 2 additions & 2 deletions libraries/libvapours/include/vapours/ams/ams_api_version.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#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_SUPPORTED_HOS_VERSION_MAJOR 14
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MINOR 1
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 0
#define ATMOSPHERE_SUPPORTED_HOS_VERSION_MICRO 1
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@
#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_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_MAX ATMOSPHERE_TARGET_FIRMWARE_CURRENT
Expand Down Expand Up @@ -132,6 +133,7 @@ namespace ams {
TargetFirmware_13_2_1 = ATMOSPHERE_TARGET_FIRMWARE_13_2_1,
TargetFirmware_14_0_0 = ATMOSPHERE_TARGET_FIRMWARE_14_0_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,

Expand Down

0 comments on commit 3545c0a

Please sign in to comment.