Compare commits

..

5 Commits

Author SHA1 Message Date
Michael Scire
965e05b3cc ams: bump version to 1.6.1 2023-10-16 12:30:46 -07:00
Michael Scire
944ff3d5f6 ncm: fix two comments 2023-10-16 12:30:44 -07:00
Michael Scire
2125f3c404 ncm: better detect + fix 17 brick after-the-fact
This adds detection for missing-save or empty-save, and rebuilds in either case.
2023-10-16 12:30:44 -07:00
Liam
8d495c256e fs: add missing stub for GetProgramId 2023-10-16 12:30:44 -07:00
Michael Scire
74d96b5fea kern: fix minor sin 2023-10-16 12:30:43 -07:00
5 changed files with 69 additions and 19 deletions

View File

@ -583,7 +583,7 @@ namespace ams::kern {
/* Check memory state. */ /* Check memory state. */
const KProcessAddress last_addr = addr + size - 1; const KProcessAddress last_addr = addr + size - 1;
KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr); KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr);
R_TRY(this->CheckMemoryState(out_state, out_perm, out_attr, out_blocks_needed, it, last_addr, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr)) R_TRY(this->CheckMemoryState(out_state, out_perm, out_attr, out_blocks_needed, it, last_addr, state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr));
/* If the start address isn't aligned, we need a block. */ /* If the start address isn't aligned, we need a block. */
if (out_blocks_needed != nullptr && util::AlignDown(GetInteger(addr), PageSize) != it->GetAddress()) { if (out_blocks_needed != nullptr && util::AlignDown(GetInteger(addr), PageSize) != it->GetAddress()) {

View File

@ -239,8 +239,12 @@ namespace ams::ncm {
Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count); Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
Result BuildContentMetaDatabase(StorageId storage_id); Result BuildContentMetaDatabase(StorageId storage_id);
Result BuildContentMetaDatabaseImpl(StorageId storage_id);
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition); Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name); Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
private:
/* Helpers for unofficial functionality. */
bool IsNeedRebuildSystemContentMetaDatabase();
public: public:
/* Actual commands. */ /* Actual commands. */
Result CreateContentStorage(StorageId storage_id); Result CreateContentStorage(StorageId storage_id);

View File

@ -307,6 +307,10 @@ namespace ams::fssrv {
AMS_ABORT("TODO"); AMS_ABORT("TODO");
} }
Result FileSystemProxyImpl::GetProgramId(ams::sf::Out<ncm::ProgramId> out_program_id, const fssrv::sf::FspPath &path, fs::ContentAttributes attr) {
AMS_ABORT("TODO");
}
Result FileSystemProxyImpl::GetRightsIdByPath(ams::sf::Out<fs::RightsId> out, const fssrv::sf::FspPath &path) { Result FileSystemProxyImpl::GetRightsIdByPath(ams::sf::Out<fs::RightsId> out, const fssrv::sf::FspPath &path) {
AMS_ABORT("TODO"); AMS_ABORT("TODO");
} }

View File

@ -784,27 +784,31 @@ namespace ams::ncm {
} }
Result ContentManagerImpl::BuildContentMetaDatabase(StorageId storage_id) { Result ContentManagerImpl::BuildContentMetaDatabase(StorageId storage_id) {
/* NOTE: we build on 17.0.0+, to work around a change in Nintendo save handling behavior. */ if (hos::GetVersion() < hos::Version_5_0_0) {
if (hos::GetVersion() < hos::Version_5_0_0 || hos::GetVersion() >= hos::Version_17_0_0) { /* On < 5.0.0, perform an actual build of the database. */
/* Temporarily activate the database. */ R_RETURN(this->BuildContentMetaDatabaseImpl(storage_id));
R_TRY(this->ActivateContentMetaDatabase(storage_id));
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); };
/* Open the content meta database and storage. */
ContentMetaDatabase meta_db;
ContentStorage storage;
R_TRY(ncm::OpenContentMetaDatabase(std::addressof(meta_db), storage_id));
R_TRY(ncm::OpenContentStorage(std::addressof(storage), storage_id));
/* Create a builder, and build. */
ContentMetaDatabaseBuilder builder(std::addressof(meta_db));
R_RETURN(builder.BuildFromStorage(std::addressof(storage)));
} else { } else {
/* On 5.0.0+, building just performs an import. */ /* On 5.0.0+, building just performs an import. */
R_RETURN(this->ImportContentMetaDatabase(storage_id, false)); R_RETURN(this->ImportContentMetaDatabase(storage_id, false));
} }
} }
Result ContentManagerImpl::BuildContentMetaDatabaseImpl(StorageId storage_id) {
/* Temporarily activate the database. */
R_TRY(this->ActivateContentMetaDatabase(storage_id));
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(storage_id); };
/* Open the content meta database and storage. */
ContentMetaDatabase meta_db;
ContentStorage storage;
R_TRY(ncm::OpenContentMetaDatabase(std::addressof(meta_db), storage_id));
R_TRY(ncm::OpenContentStorage(std::addressof(storage), storage_id));
/* Create a builder, and build. */
ContentMetaDatabaseBuilder builder(std::addressof(meta_db));
R_RETURN(builder.BuildFromStorage(std::addressof(storage)));
}
Result ContentManagerImpl::ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition) { Result ContentManagerImpl::ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition) {
/* Only support importing BuiltInSystem. */ /* Only support importing BuiltInSystem. */
AMS_ABORT_UNLESS(storage_id == StorageId::BuiltInSystem); AMS_ABORT_UNLESS(storage_id == StorageId::BuiltInSystem);
@ -832,6 +836,31 @@ namespace ams::ncm {
R_SUCCEED(); R_SUCCEED();
} }
bool ContentManagerImpl::IsNeedRebuildSystemContentMetaDatabase() {
/* TODO: Should hos::GetVersion() >= hos::Version_17_0_0 be checked? */
/* If we do not actually have a content meta db, we should re-build. */
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
return true;
}
/* We have a content meta db. Temporarily, activate it. */
if (R_FAILED(this->ActivateContentMetaDatabase(StorageId::BuiltInSystem))) {
return true;
}
ON_SCOPE_EXIT { this->InactivateContentMetaDatabase(StorageId::BuiltInSystem); };
/* Open the content meta db. */
ContentMetaDatabase meta_db;
R_ABORT_UNLESS(ncm::OpenContentMetaDatabase(std::addressof(meta_db), StorageId::BuiltInSystem));
/* List the meta db's contents. */
const auto list_count = meta_db.ListContentMeta(nullptr, 0);
/* We need to rebuild if the db has zero entries. */
return list_count.total == 0;
}
Result ContentManagerImpl::Initialize(const ContentManagerConfig &config) { Result ContentManagerImpl::Initialize(const ContentManagerConfig &config) {
/* Initialize based on whether integrated content is enabled. */ /* Initialize based on whether integrated content is enabled. */
if (config.IsIntegratedSystemContentEnabled()) { if (config.IsIntegratedSystemContentEnabled()) {
@ -942,13 +971,26 @@ namespace ams::ncm {
} }
R_TRY(this->ActivateContentStorage(StorageId::BuiltInSystem)); R_TRY(this->ActivateContentStorage(StorageId::BuiltInSystem));
/* NOTE: This logic is unofficial. */
/* Beginning with 17.0.0+, save management behavior changed. The primary symptom of this is either verify fail */
/* or an empty kvs, both of which we can fix by performing a rebuild. */
if (this->IsNeedRebuildSystemContentMetaDatabase()) {
/* Clean up the system content meta database, to ensure creation can succeed. */
this->CleanupContentMetaDatabase(StorageId::BuiltInSystem);
/* Create the content meta database. */
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
/* Rebuild the content meta database. */
R_TRY(this->BuildContentMetaDatabaseImpl(StorageId::BuiltInSystem));
}
/* Setup the content meta database for system. */ /* Setup the content meta database for system. */
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) { if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem)); R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
/* Try to build or import a database, depending on our configuration. */ /* Try to build or import a database, depending on our configuration. */
/* NOTE: To work around a change in save management behavior in 17.0.0+, we build the database if needed. */ if (manager_config.ShouldBuildDatabase()) {
if (manager_config.ShouldBuildDatabase() || hos::GetVersion() >= hos::Version_17_0_0) {
/* If we should build the database, do so. */ /* If we should build the database, do so. */
R_TRY(this->BuildContentMetaDatabase(StorageId::BuiltInSystem)); R_TRY(this->BuildContentMetaDatabase(StorageId::BuiltInSystem));
R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem)); R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem));

View File

@ -17,7 +17,7 @@
#define ATMOSPHERE_RELEASE_VERSION_MAJOR 1 #define ATMOSPHERE_RELEASE_VERSION_MAJOR 1
#define ATMOSPHERE_RELEASE_VERSION_MINOR 6 #define ATMOSPHERE_RELEASE_VERSION_MINOR 6
#define ATMOSPHERE_RELEASE_VERSION_MICRO 0 #define ATMOSPHERE_RELEASE_VERSION_MICRO 1
#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