mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
ncm: implement ncm.for-initialize + ncm.for-safemode
This commit is contained in:
parent
6fa9276e57
commit
67c858e297
12 changed files with 388 additions and 9 deletions
|
@ -35,9 +35,11 @@
|
|||
#include <stratosphere/fs/fs_romfs_filesystem.hpp>
|
||||
#include <stratosphere/fs/impl/fs_data.hpp>
|
||||
#include <stratosphere/fs/fs_system_data.hpp>
|
||||
#include <stratosphere/fs/fs_bis.hpp>
|
||||
#include <stratosphere/fs/fs_content_storage.hpp>
|
||||
#include <stratosphere/fs/fs_game_card.hpp>
|
||||
#include <stratosphere/fs/fs_sd_card.hpp>
|
||||
#include <stratosphere/fs/fs_signed_system_partition.hpp>
|
||||
#include <stratosphere/fs/fs_save_data_types.hpp>
|
||||
#include <stratosphere/fs/fs_save_data_management.hpp>
|
||||
#include <stratosphere/fs/fs_save_data_transaction.hpp>
|
||||
|
|
58
libraries/libstratosphere/include/stratosphere/fs/fs_bis.hpp
Normal file
58
libraries/libstratosphere/include/stratosphere/fs/fs_bis.hpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere/fs/fs_common.hpp>
|
||||
#include <stratosphere/fs/fs_istorage.hpp>
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
enum class BisPartitionId {
|
||||
/* Boot0 */
|
||||
BootPartition1Root = 0,
|
||||
|
||||
/* Boot1 */
|
||||
BootPartition2Root = 10,
|
||||
|
||||
/* Non-Boot */
|
||||
UserDataRoot = 20,
|
||||
BootConfigAndPackage2Part1 = 21,
|
||||
BootConfigAndPackage2Part2 = 22,
|
||||
BootConfigAndPackage2Part3 = 23,
|
||||
BootConfigAndPackage2Part4 = 24,
|
||||
BootConfigAndPackage2Part5 = 25,
|
||||
BootConfigAndPackage2Part6 = 26,
|
||||
CalibrationBinary = 27,
|
||||
CalibrationFile = 28,
|
||||
SafeMode = 29,
|
||||
User = 30,
|
||||
System = 31,
|
||||
SystemProperEncryption = 32,
|
||||
SystemProperPartition = 33,
|
||||
SignedSystemPartitionOnSafeMode = 34,
|
||||
};
|
||||
|
||||
const char *GetBisMountName(BisPartitionId id);
|
||||
|
||||
Result MountBis(BisPartitionId id, const char *root_path);
|
||||
Result MountBis(const char *name, BisPartitionId id);
|
||||
|
||||
void SetBisRootForHost(BisPartitionId id, const char *root_path);
|
||||
|
||||
Result OpenBisPartition(std::unique_ptr<fs::IStorage> *out, BisPartitionId id);
|
||||
|
||||
Result InvalidateBisCache();
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "fs_common.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
bool IsSignedSystemPartitionOnSdCardValid(const char *system_root_path);
|
||||
bool IsSignedSystemPartitionOnSdCardValidDeprecated();
|
||||
|
||||
}
|
|
@ -24,7 +24,8 @@ namespace ams::fs::fsa {
|
|||
class IDirectory;
|
||||
|
||||
enum class QueryId {
|
||||
SetConcatenationFileAttribute = FsFileSystemQueryId_SetConcatenationFileAttribute
|
||||
SetConcatenationFileAttribute = 0,
|
||||
IsSignedSystemPartitionOnSdCardValid = 2,
|
||||
};
|
||||
|
||||
class IFileSystem {
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <vapours.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
struct ContentManagerConfig {
|
||||
bool import_database_from_system;
|
||||
bool import_database_from_system_on_sd;
|
||||
|
||||
constexpr bool HasAnyImport() const {
|
||||
return this->import_database_from_system || this->import_database_from_system_on_sd;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -15,10 +15,12 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <stratosphere/os.hpp>
|
||||
#include <stratosphere/fs/fs_content_storage.hpp>
|
||||
#include <stratosphere/fs/fs_mount.hpp>
|
||||
#include <stratosphere/fs/fs_bis.hpp>
|
||||
#include <stratosphere/fs/fs_content_storage.hpp>
|
||||
#include <stratosphere/fs/fs_system_save_data.hpp>
|
||||
#include <stratosphere/ncm/ncm_i_content_manager.hpp>
|
||||
#include <stratosphere/ncm/ncm_content_manager_config.hpp>
|
||||
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
|
||||
#include <stratosphere/ncm/ncm_bounded_map.hpp>
|
||||
#include <stratosphere/ncm/ncm_rights_id_cache.hpp>
|
||||
|
@ -68,7 +70,7 @@ namespace ams::ncm {
|
|||
ContentMetaDatabaseRoot() { /* ... */ }
|
||||
};
|
||||
private:
|
||||
os::Mutex mutex;
|
||||
os::RecursiveMutex mutex;
|
||||
bool initialized;
|
||||
ContentStorageRoot content_storage_roots[MaxContentStorageRoots];
|
||||
ContentMetaDatabaseRoot content_meta_database_roots[MaxContentMetaDatabaseRoots];
|
||||
|
@ -79,7 +81,7 @@ namespace ams::ncm {
|
|||
ContentManagerImpl() : initialized(false) { /* ... */ };
|
||||
~ContentManagerImpl();
|
||||
public:
|
||||
Result Initialize();
|
||||
Result Initialize(const ContentManagerConfig &config);
|
||||
private:
|
||||
/* Helpers. */
|
||||
Result GetContentStorageRoot(ContentStorageRoot **out, StorageId id);
|
||||
|
@ -91,8 +93,9 @@ namespace ams::ncm {
|
|||
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, const SystemSaveDataInfo &info, size_t max_content_metas);
|
||||
Result InitializeGameCardContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, size_t max_content_metas);
|
||||
|
||||
Result EnsureAndMountSystemSaveData(const char *mount, const SystemSaveDataInfo &info) const;
|
||||
Result ImportContentMetaDatabase(StorageId storage_id, const char *import_mount_name, const char *path);
|
||||
|
||||
Result EnsureAndMountSystemSaveData(const char *mount, const SystemSaveDataInfo &info) const;
|
||||
public:
|
||||
/* Actual commands. */
|
||||
virtual Result CreateContentStorage(StorageId storage_id) override;
|
||||
|
|
127
libraries/libstratosphere/source/fs/fs_bis.cpp
Normal file
127
libraries/libstratosphere/source/fs/fs_bis.cpp
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
namespace {
|
||||
|
||||
class BisCommonMountNameGenerator : public fsa::ICommonMountNameGenerator, public impl::Newable {
|
||||
private:
|
||||
const BisPartitionId id;
|
||||
public:
|
||||
explicit BisCommonMountNameGenerator(BisPartitionId i) : id(i) { /* ... */ }
|
||||
|
||||
virtual Result GenerateCommonMountName(char *dst, size_t dst_size) override {
|
||||
/* Determine how much space we need. */
|
||||
const char *bis_mount_name = GetBisMountName(this->id);
|
||||
const size_t needed_size = strnlen(bis_mount_name, MountNameLengthMax) + 2;
|
||||
AMS_ABORT_UNLESS(dst_size >= needed_size);
|
||||
|
||||
/* Generate the name. */
|
||||
auto size = std::snprintf(dst, dst_size, "%s:", bis_mount_name);
|
||||
AMS_ASSERT(static_cast<size_t>(size) == needed_size - 1);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
Result MountBisImpl(const char *name, BisPartitionId id, const char *root_path) {
|
||||
/* Validate the mount name. */
|
||||
R_TRY(impl::CheckMountNameAllowingReserved(name));
|
||||
|
||||
/* Open the partition. This uses libnx bindings. */
|
||||
/* Note: Nintendo ignores the root_path here. */
|
||||
FsFileSystem fs;
|
||||
R_TRY(fsOpenBisFileSystem(std::addressof(fs), static_cast<::FsBisPartitionId>(id), ""));
|
||||
|
||||
/* Allocate a new mountname generator. */
|
||||
std::unique_ptr<BisCommonMountNameGenerator> generator(new BisCommonMountNameGenerator(id));
|
||||
R_UNLESS(generator != nullptr, fs::ResultAllocationFailureInBisA());
|
||||
|
||||
/* Allocate a new filesystem wrapper. */
|
||||
std::unique_ptr<fsa::IFileSystem> fsa(new RemoteFileSystem(fs));
|
||||
R_UNLESS(fsa != nullptr, fs::ResultAllocationFailureInBisB());
|
||||
|
||||
/* Register. */
|
||||
return fsa::Register(name, std::move(fsa), std::move(generator));
|
||||
}
|
||||
|
||||
Result SetBisRootForHostImpl(BisPartitionId id, const char *root_path) {
|
||||
/* Ensure the path isn't too long. */
|
||||
size_t len = strnlen(root_path, fs::EntryNameLengthMax + 1);
|
||||
R_UNLESS(len <= fs::EntryNameLengthMax, fs::ResultTooLongPath());
|
||||
|
||||
fssrv::sf::Path sf_path;
|
||||
if (len > 0) {
|
||||
const bool ending_sep = PathTool::IsSeparator(root_path[len - 1]);
|
||||
FspPathPrintf(std::addressof(sf_path), "%s%s", root_path, ending_sep ? "" : "/");
|
||||
} else {
|
||||
sf_path.str[0] = '\x00';
|
||||
}
|
||||
|
||||
/* TODO: Libnx binding for fsSetBisRootForHost */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const char *GetBisMountName(BisPartitionId id) {
|
||||
switch (id) {
|
||||
case BisPartitionId::CalibrationFile: return impl::BisCalibrationFilePartitionMountName;
|
||||
case BisPartitionId::SafeMode: return impl::BisSafeModePartitionMountName;
|
||||
case BisPartitionId::User: return impl::BisUserPartitionMountName;
|
||||
case BisPartitionId::System: return impl::BisSystemPartitionMountName;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
Result MountBis(BisPartitionId id, const char *root_path) {
|
||||
return impl::MountBisImpl(GetBisMountName(id), id, root_path);
|
||||
}
|
||||
|
||||
Result MountBis(const char *name, BisPartitionId id) {
|
||||
return impl::MountBisImpl(name, id, nullptr);
|
||||
}
|
||||
|
||||
void SetBisRootForHost(BisPartitionId id, const char *root_path) {
|
||||
R_ABORT_UNLESS(impl::SetBisRootForHostImpl(id, root_path));
|
||||
}
|
||||
|
||||
Result OpenBisPartition(std::unique_ptr<fs::IStorage> *out, BisPartitionId id) {
|
||||
/* Open the partition. This uses libnx bindings. */
|
||||
FsStorage s;
|
||||
R_TRY(fsOpenBisStorage(std::addressof(s), static_cast<::FsBisPartitionId>(id)));
|
||||
|
||||
/* Allocate a new storage wrapper. */
|
||||
std::unique_ptr<fs::IStorage> storage(new RemoteStorage(s));
|
||||
R_UNLESS(storage != nullptr, fs::ResultAllocationFailureInBisC());
|
||||
|
||||
*out = std::move(storage);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result InvalidateBisCache() {
|
||||
/* TODO: Libnx binding for this command. */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
#include "fsa/fs_filesystem_accessor.hpp"
|
||||
#include "fsa/fs_mount_utils.hpp"
|
||||
|
||||
namespace ams::fs {
|
||||
|
||||
bool IsSignedSystemPartitionOnSdCardValid(const char *system_root_path) {
|
||||
/* Get the accessor for the system filesystem. */
|
||||
impl::FileSystemAccessor *accessor;
|
||||
const char *sub_path;
|
||||
R_ABORT_UNLESS(impl::FindFileSystem(std::addressof(accessor), std::addressof(sub_path), system_root_path));
|
||||
|
||||
char is_valid;
|
||||
R_TRY_CATCH(accessor->QueryEntry(std::addressof(is_valid), 1, nullptr, 0, fsa::QueryId::IsSignedSystemPartitionOnSdCardValid, "/")) {
|
||||
/* If querying isn't supported, then the partition isn't valid. */
|
||||
R_CATCH(fs::ResultUnsupportedOperation) { is_valid = false; }
|
||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
bool IsSignedSystemPartitionOnSdCardValidDeprecated() {
|
||||
/* Ensure we only call with correct version. */
|
||||
auto version = hos::GetVersion();
|
||||
AMS_ABORT_UNLESS(hos::Version_400 <= version && version < hos::Version_800);
|
||||
|
||||
/* Check that the partition is valid. */
|
||||
bool is_valid;
|
||||
R_ABORT_UNLESS(fsIsSignedSystemPartitionOnSdCardValid(std::addressof(is_valid)));
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
}
|
|
@ -156,7 +156,6 @@ namespace ams::fs {
|
|||
return accessor->GetTotalSpaceSize(out, sub_path);
|
||||
}
|
||||
|
||||
|
||||
Result SetConcatenationFileAttribute(const char *path) {
|
||||
impl::FileSystemAccessor *accessor;
|
||||
const char *sub_path;
|
||||
|
|
|
@ -107,6 +107,28 @@ namespace ams::ncm {
|
|||
default: return ResultUnknownContentMetaDatabaseNotActive();
|
||||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE bool ShouldPerformImport(const ContentManagerConfig &config, const char *bis_mount_name) {
|
||||
AMS_ASSERT(config.HasAnyImport());
|
||||
if (config.import_database_from_system) {
|
||||
/* If we're importing from system, just do the import. */
|
||||
return true;
|
||||
} else /* if (config.import_database_from_system_on_sd) */ {
|
||||
/* If we're importing from system on SD, make sure that the signed system partition is valid. */
|
||||
const auto version = hos::GetVersion();
|
||||
if (version >= hos::Version_800 || version < hos::Version_400) {
|
||||
/* On >= 8.0.0, a simpler method was added to check validity. */
|
||||
/* This also works on < 4.0.0 (though the system partition will never be on-sd there), */
|
||||
/* and so this will always return false. */
|
||||
char path[fs::MountNameLengthMax + 2 /* :/ */ + 1];
|
||||
std::snprintf(path, sizeof(path), "%s:/", bis_mount_name);
|
||||
return fs::IsSignedSystemPartitionOnSdCardValid(path);
|
||||
} else {
|
||||
/* On 4.0.0-7.0.1, use the remote command to validate the system partition. */
|
||||
return fs::IsSignedSystemPartitionOnSdCardValidDeprecated();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ContentManagerImpl::~ContentManagerImpl() {
|
||||
|
@ -218,7 +240,36 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentManagerImpl::Initialize() {
|
||||
Result ContentManagerImpl::ImportContentMetaDatabase(StorageId storage_id, const char *import_mount_name, const char *path) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
|
||||
/* Obtain the content meta database root. */
|
||||
ContentMetaDatabaseRoot *root;
|
||||
R_TRY(this->GetContentMetaDatabaseRoot(&root, storage_id));
|
||||
|
||||
/* Print the savedata path. */
|
||||
PathString savedata_db_path;
|
||||
savedata_db_path.SetFormat("%s/%s", root->path, "imkvdb.arc");
|
||||
|
||||
/* Print a path for the mounted partition. */
|
||||
PathString bis_db_path;
|
||||
bis_db_path.SetFormat("%s:/%s", import_mount_name, path);
|
||||
|
||||
/* Mount the savedata. */
|
||||
R_TRY(fs::MountSystemSaveData(root->mount_name, root->info.space_id, root->info.id));
|
||||
ON_SCOPE_EXIT { fs::Unmount(root->mount_name); };
|
||||
|
||||
/* Ensure the path exists for us to import to. */
|
||||
R_TRY(impl::EnsureDirectoryRecursively(root->path));
|
||||
|
||||
/* Copy the file from bis to our save. */
|
||||
R_TRY(impl::CopyFile(savedata_db_path, bis_db_path));
|
||||
|
||||
/* Commit the import. */
|
||||
return fs::CommitSaveData(root->mount_name);
|
||||
}
|
||||
|
||||
Result ContentManagerImpl::Initialize(const ContentManagerConfig &config) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
|
||||
/* Check if we've already initialized. */
|
||||
|
@ -246,7 +297,23 @@ namespace ams::ncm {
|
|||
if (R_FAILED(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem))) {
|
||||
R_TRY(this->CreateContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
|
||||
/* TODO: N supports building the database depending on config (unused on retail). */
|
||||
/* NOTE: Nintendo added support for building/importing in 4.0.0. */
|
||||
/* However, there's no reason to restrict this on a per-version basis. */
|
||||
|
||||
/* If we should import the database from system, do so and verify it. */
|
||||
if (config.HasAnyImport()) {
|
||||
/* Get a mount name for the system partition. */
|
||||
auto bis_mount_name = impl::CreateUniqueMountName();
|
||||
|
||||
/* Mount the BIS partition that contains the database we're importing. */
|
||||
R_TRY(fs::MountBis(bis_mount_name.str, fs::BisPartitionId::System));
|
||||
ON_SCOPE_EXIT { fs::Unmount(bis_mount_name.str); };
|
||||
|
||||
if (ShouldPerformImport(config, bis_mount_name.str)) {
|
||||
R_TRY(this->ImportContentMetaDatabase(StorageId::BuiltInSystem, bis_mount_name.str, "cnmtdb.arc"));
|
||||
R_TRY(this->VerifyContentMetaDatabase(StorageId::BuiltInSystem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure correct flags on the BuiltInSystem save data. */
|
||||
|
|
|
@ -53,6 +53,9 @@ namespace ams::fs {
|
|||
R_DEFINE_ERROR_RANGE(AllocationFailure, 3200, 3499);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorA, 3211);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemAccessorB, 3212);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInBisA, 3215);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInBisB, 3216);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInBisC, 3217);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageA, 3220);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInContentStorageB, 3221);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInDataA, 3222);
|
||||
|
|
|
@ -187,13 +187,30 @@ namespace {
|
|||
return sf::ServiceObjectTraits<ncm::ContentManagerImpl>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_ncm_manager_service_object));
|
||||
}
|
||||
|
||||
/* Compile-time configuration. */
|
||||
#ifdef NCM_BUILD_FOR_INTITIALIZE
|
||||
constexpr inline bool ImportSystemDatabase = true;
|
||||
#else
|
||||
constexpr inline bool ImportSystemDatabase = false;
|
||||
#endif
|
||||
|
||||
#ifdef NCM_BUILD_FOR_SAFEMODE
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = true;
|
||||
#else
|
||||
constexpr inline bool ImportSystemDatabaseFromSignedSystemPartitionOnSdCard = false;
|
||||
#endif
|
||||
|
||||
static_assert(!(ImportSystemDatabase && ImportSystemDatabaseFromSignedSystemPartitionOnSdCard), "Invalid NCM build configuration!");
|
||||
|
||||
constexpr inline ncm::ContentManagerConfig ManagerConfig = { ImportSystemDatabase, ImportSystemDatabaseFromSignedSystemPartitionOnSdCard };
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
/* Create and initialize the content manager. */
|
||||
auto content_manager = GetSharedPointerToContentManager();
|
||||
R_ABORT_UNLESS(content_manager->Initialize());
|
||||
R_ABORT_UNLESS(content_manager->Initialize(ManagerConfig));
|
||||
|
||||
/* Initialize ncm's server and start threads. */
|
||||
R_ABORT_UNLESS(g_ncm_server_manager.Initialize(content_manager));
|
||||
|
|
Loading…
Add table
Reference in a new issue