Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"
This reverts commit 15b7df8ef1.
This commit is contained in:
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv::fscreator {
|
||||
|
||||
Result LocalFileSystemCreator::Create(std::shared_ptr<fs::fsa::IFileSystem> *out, const fs::Path &path, bool case_sensitive, bool ensure_root, Result on_path_not_found) {
|
||||
/* Check that we're configured for development. */
|
||||
R_UNLESS(m_is_development, fs::ResultPermissionDeniedForCreateHostFileSystem());
|
||||
|
||||
/* Allocate a local filesystem. */
|
||||
auto local_fs = fs::AllocateShared<fssystem::LocalFileSystem>();
|
||||
R_UNLESS(local_fs != nullptr, fs::ResultAllocationMemoryFailedInLocalFileSystemCreatorA());
|
||||
|
||||
/* If we're supposed to make sure the root path exists, do so. */
|
||||
if (ensure_root) {
|
||||
/* Sanity check that the path will be possible to create. */
|
||||
AMS_ASSERT(!path.IsEmpty());
|
||||
|
||||
/* Initialize the local fs with an empty path. */
|
||||
fs::Path empty_path;
|
||||
R_TRY(empty_path.InitializeAsEmpty());
|
||||
R_TRY(local_fs->Initialize(empty_path, fssystem::PathCaseSensitiveMode_CaseInsensitive));
|
||||
|
||||
/* Ensure the directory exists. */
|
||||
if (const Result ensure_result = fssystem::EnsureDirectory(local_fs.get(), path); R_FAILED(ensure_result)) {
|
||||
if (R_SUCCEEDED(on_path_not_found)) {
|
||||
R_THROW(ensure_result);
|
||||
} else {
|
||||
R_THROW(on_path_not_found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the local filesystem. */
|
||||
R_TRY_CATCH(local_fs->Initialize(path, case_sensitive ? fssystem::PathCaseSensitiveMode_CaseSensitive : fssystem::PathCaseSensitiveMode_CaseInsensitive)) {
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
if (R_SUCCEEDED(on_path_not_found)) {
|
||||
R_THROW(R_CURRENT_RESULT);
|
||||
} else {
|
||||
R_THROW(on_path_not_found);
|
||||
}
|
||||
}
|
||||
} R_END_TRY_CATCH;
|
||||
|
||||
/* Set the output fs. */
|
||||
*out = std::move(local_fs);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv::fscreator {
|
||||
|
||||
Result PartitionFileSystemCreator::Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::IStorage> storage) {
|
||||
/* Allocate a filesystem. */
|
||||
std::shared_ptr fs = fssystem::AllocateShared<fssystem::PartitionFileSystem>();
|
||||
R_UNLESS(fs != nullptr, fs::ResultAllocationMemoryFailedInPartitionFileSystemCreatorA());
|
||||
|
||||
/* Initialize the filesystem. */
|
||||
R_TRY(fs->Initialize(std::move(storage)));
|
||||
|
||||
/* Set the output. */
|
||||
*out = std::move(fs);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv::fscreator {
|
||||
|
||||
namespace {
|
||||
|
||||
class RomFileSystemWithBuffer : public ::ams::fssystem::RomFsFileSystem {
|
||||
private:
|
||||
void *m_meta_cache_buffer;
|
||||
size_t m_meta_cache_buffer_size;
|
||||
MemoryResource *m_allocator;
|
||||
public:
|
||||
explicit RomFileSystemWithBuffer(MemoryResource *mr) : m_meta_cache_buffer(nullptr), m_allocator(mr) { /* ... */ }
|
||||
|
||||
~RomFileSystemWithBuffer() {
|
||||
if (m_meta_cache_buffer != nullptr) {
|
||||
m_allocator->Deallocate(m_meta_cache_buffer, m_meta_cache_buffer_size);
|
||||
}
|
||||
}
|
||||
|
||||
Result Initialize(std::shared_ptr<fs::IStorage> storage) {
|
||||
/* Check if the buffer is eligible for cache. */
|
||||
size_t buffer_size = 0;
|
||||
if (R_FAILED(RomFsFileSystem::GetRequiredWorkingMemorySize(std::addressof(buffer_size), storage.get())) || buffer_size == 0 || buffer_size >= 128_KB) {
|
||||
R_RETURN(RomFsFileSystem::Initialize(std::move(storage), nullptr, 0, false));
|
||||
}
|
||||
|
||||
/* Allocate a buffer. */
|
||||
m_meta_cache_buffer = m_allocator->Allocate(buffer_size);
|
||||
if (m_meta_cache_buffer == nullptr) {
|
||||
R_RETURN(RomFsFileSystem::Initialize(std::move(storage), nullptr, 0, false));
|
||||
}
|
||||
|
||||
/* Initialize with cache buffer. */
|
||||
m_meta_cache_buffer_size = buffer_size;
|
||||
R_RETURN(RomFsFileSystem::Initialize(std::move(storage), m_meta_cache_buffer, m_meta_cache_buffer_size, true));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Result RomFileSystemCreator::Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::IStorage> storage) {
|
||||
/* Allocate a filesystem. */
|
||||
std::shared_ptr fs = fssystem::AllocateShared<RomFileSystemWithBuffer>(m_allocator);
|
||||
R_UNLESS(fs != nullptr, fs::ResultAllocationMemoryFailedInRomFileSystemCreatorA());
|
||||
|
||||
/* Initialize the filesystem. */
|
||||
R_TRY(fs->Initialize(std::move(storage)));
|
||||
|
||||
/* Set the output. */
|
||||
*out = std::move(fs);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv::fscreator {
|
||||
|
||||
Result StorageOnNcaCreator::Create(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, std::shared_ptr<fssystem::NcaReader> nca_reader, s32 index) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
std::shared_ptr<fssystem::IAsynchronousAccessSplitter> splitter;
|
||||
R_TRY(nca_fs_driver.OpenStorage(std::addressof(storage), std::addressof(splitter), out_header_reader, index));
|
||||
|
||||
/* Set the out storage. */
|
||||
*out = std::move(storage);
|
||||
*out_splitter = std::move(splitter);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StorageOnNcaCreator::CreateWithPatch(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, std::shared_ptr<fssystem::NcaReader> original_nca_reader, std::shared_ptr<fssystem::NcaReader> current_nca_reader, s32 index) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(original_nca_reader, current_nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
std::shared_ptr<fssystem::IAsynchronousAccessSplitter> splitter;
|
||||
R_TRY(nca_fs_driver.OpenStorage(std::addressof(storage), std::addressof(splitter), out_header_reader, index));
|
||||
|
||||
/* Set the out storage. */
|
||||
*out = std::move(storage);
|
||||
*out_splitter = std::move(splitter);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StorageOnNcaCreator::CreateNcaReader(std::shared_ptr<fssystem::NcaReader> *out, std::shared_ptr<fs::IStorage> storage) {
|
||||
/* Create a reader. */
|
||||
std::shared_ptr reader = fssystem::AllocateShared<fssystem::NcaReader>();
|
||||
R_UNLESS(reader != nullptr, fs::ResultAllocationMemoryFailedInStorageOnNcaCreatorB());
|
||||
|
||||
/* Initialize the reader. */
|
||||
R_TRY(reader->Initialize(std::move(storage), m_nca_crypto_cfg, m_nca_compression_cfg, m_hash_generator_factory_selector));
|
||||
|
||||
/* Set the output. */
|
||||
*out = std::move(reader);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
#if !defined(ATMOSPHERE_BOARD_NINTENDO_NX)
|
||||
Result StorageOnNcaCreator::CreateWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader, s32 index) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
std::shared_ptr<fssystem::IAsynchronousAccessSplitter> splitter;
|
||||
R_TRY(nca_fs_driver.OpenStorageWithContext(std::addressof(storage), std::addressof(splitter), out_header_reader, index, static_cast<fssystem::NcaFileSystemDriver::StorageContext *>(ctx)));
|
||||
|
||||
/* Set the out storage. */
|
||||
*out = std::move(storage);
|
||||
*out_splitter = std::move(splitter);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StorageOnNcaCreator::CreateWithPatchWithContext(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, fssystem::NcaFsHeaderReader *out_header_reader, void *ctx, std::shared_ptr<fssystem::NcaReader> original_nca_reader, std::shared_ptr<fssystem::NcaReader> current_nca_reader, s32 index) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(original_nca_reader, current_nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||
|
||||
/* Open the storage. */
|
||||
std::shared_ptr<fs::IStorage> storage;
|
||||
std::shared_ptr<fssystem::IAsynchronousAccessSplitter> splitter;
|
||||
R_TRY(nca_fs_driver.OpenStorageWithContext(std::addressof(storage), std::addressof(splitter), out_header_reader, index, static_cast<fssystem::NcaFileSystemDriver::StorageContext *>(ctx)));
|
||||
|
||||
/* Set the out storage. */
|
||||
*out = std::move(storage);
|
||||
*out_splitter = std::move(splitter);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result StorageOnNcaCreator::CreateByRawStorage(std::shared_ptr<fs::IStorage> *out, std::shared_ptr<fssystem::IAsynchronousAccessSplitter> *out_splitter, const fssystem::NcaFsHeaderReader *header_reader, std::shared_ptr<fs::IStorage> raw_storage, void *ctx, std::shared_ptr<fssystem::NcaReader> nca_reader) {
|
||||
/* Create a fs driver. */
|
||||
fssystem::NcaFileSystemDriver nca_fs_driver(nca_reader, m_allocator, m_buffer_manager, m_hash_generator_factory_selector);
|
||||
|
||||
/* Open the storage. */
|
||||
auto *storage_ctx = static_cast<fssystem::NcaFileSystemDriver::StorageContext *>(ctx);
|
||||
R_TRY(nca_fs_driver.CreateStorageByRawStorage(out, header_reader, std::move(raw_storage), storage_ctx));
|
||||
|
||||
/* Update the splitter. */
|
||||
if (storage_ctx->compressed_storage != nullptr) {
|
||||
*out_splitter = storage_ctx->compressed_storage;
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv::fscreator {
|
||||
|
||||
Result SubDirectoryFileSystemCreator::Create(std::shared_ptr<fs::fsa::IFileSystem> *out, std::shared_ptr<fs::fsa::IFileSystem> base_fs, const fs::Path &path) {
|
||||
/* Verify that we can the directory on the base filesystem. */
|
||||
{
|
||||
std::unique_ptr<fs::fsa::IDirectory> sub_dir;
|
||||
R_TRY(base_fs->OpenDirectory(std::addressof(sub_dir), path, fs::OpenDirectoryMode_Directory));
|
||||
}
|
||||
|
||||
/* Allocate a SubDirectoryFileSystem. */
|
||||
auto sub_dir_fs = fs::AllocateShared<fssystem::SubDirectoryFileSystem>(std::move(base_fs));
|
||||
R_UNLESS(sub_dir_fs != nullptr, fs::ResultAllocationMemoryFailedInSubDirectoryFileSystemCreatorA());
|
||||
|
||||
/* Initialize the new filesystem. */
|
||||
R_TRY(sub_dir_fs->Initialize(path));
|
||||
|
||||
/* Return the new filesystem. */
|
||||
*out = std::move(sub_dir_fs);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,407 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit bool g_is_debug_flag_enabled = false;
|
||||
|
||||
}
|
||||
|
||||
bool IsDebugFlagEnabled() {
|
||||
return g_is_debug_flag_enabled;
|
||||
}
|
||||
|
||||
void SetDebugFlagEnabled(bool en) {
|
||||
/* Set global debug flag. */
|
||||
g_is_debug_flag_enabled = en;
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr u8 LatestFsAccessControlInfoVersion = 1;
|
||||
|
||||
}
|
||||
|
||||
AccessControl::AccessControl(const void *data, s64 data_size, const void *desc, s64 desc_size) : AccessControl(data, data_size, desc, desc_size, g_is_debug_flag_enabled ? AllFlagBitsMask : DebugFlagDisableMask) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
AccessControl::AccessControl(const void *fac_data, s64 data_size, const void *fac_desc, s64 desc_size, u64 flag_mask) {
|
||||
/* If either our data or descriptor is null, give no permissions. */
|
||||
if (fac_data == nullptr || fac_desc == nullptr) {
|
||||
m_flag_bits.emplace(util::ToUnderlying(AccessControlBits::Bits::None));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check that data/desc are big enough. */
|
||||
AMS_ABORT_UNLESS(data_size >= static_cast<s64>(sizeof(AccessControlDataHeader)));
|
||||
AMS_ABORT_UNLESS(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor)));
|
||||
|
||||
/* Copy in the data/descriptor. */
|
||||
AccessControlDataHeader data = {};
|
||||
AccessControlDescriptor desc = {};
|
||||
std::memcpy(std::addressof(data), fac_data, sizeof(data));
|
||||
std::memcpy(std::addressof(desc), fac_desc, sizeof(desc));
|
||||
|
||||
/* If we don't know how to parse the descriptors, don't. */
|
||||
if (data.version != desc.version || data.version < LatestFsAccessControlInfoVersion) {
|
||||
m_flag_bits.emplace(util::ToUnderlying(AccessControlBits::Bits::None));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Restrict the descriptor's flag bits. */
|
||||
desc.flag_bits &= flag_mask;
|
||||
|
||||
/* Create our flag bits. */
|
||||
m_flag_bits.emplace(data.flag_bits & desc.flag_bits);
|
||||
|
||||
/* Further check sizes. */
|
||||
AMS_ABORT_UNLESS(data_size >= data.content_owner_infos_offset + data.content_owner_infos_size);
|
||||
AMS_ABORT_UNLESS(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor) + desc.content_owner_id_count * sizeof(u64)));
|
||||
|
||||
/* Read out the content data owner infos. */
|
||||
uintptr_t data_start = reinterpret_cast<uintptr_t>(fac_data);
|
||||
uintptr_t desc_start = reinterpret_cast<uintptr_t>(fac_desc);
|
||||
if (data.content_owner_infos_size > 0) {
|
||||
/* Get the count. */
|
||||
const u32 num_content_owner_infos = util::LoadLittleEndian<u32>(reinterpret_cast<u32 *>(data_start + data.content_owner_infos_offset));
|
||||
|
||||
/* Validate the id range. */
|
||||
uintptr_t id_start = data_start + data.content_owner_infos_offset + sizeof(u32);
|
||||
uintptr_t id_end = id_start + sizeof(u64) * num_content_owner_infos;
|
||||
AMS_ABORT_UNLESS(id_end == data_start + data.content_owner_infos_offset + data.content_owner_infos_size);
|
||||
|
||||
for (u32 i = 0; i < num_content_owner_infos; ++i) {
|
||||
/* Read the id. */
|
||||
const u64 id = util::LoadLittleEndian<u64>(reinterpret_cast<u64 *>(id_start + i * sizeof(u64)));
|
||||
|
||||
/* Check that the descriptor allows it. */
|
||||
bool allowed = false;
|
||||
if (desc.content_owner_id_count != 0) {
|
||||
for (u8 n = 0; n < desc.content_owner_id_count; ++n) {
|
||||
if (id == util::LoadLittleEndian<u64>(reinterpret_cast<u64 *>(desc_start + sizeof(AccessControlDescriptor) + n * sizeof(u64)))) {
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((desc.content_owner_id_min == 0 && desc.content_owner_id_max == 0) || (desc.content_owner_id_min <= id && id <= desc.content_owner_id_max)) {
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
/* If the id is allowed, create it. */
|
||||
if (allowed) {
|
||||
if (auto *info = new ContentOwnerInfo(id); info != nullptr) {
|
||||
m_content_owner_infos.push_front(*info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read out the save data owner infos. */
|
||||
AMS_ABORT_UNLESS(data_size >= data.save_data_owner_infos_offset + data.save_data_owner_infos_size);
|
||||
AMS_ABORT_UNLESS(desc_size >= static_cast<s64>(sizeof(AccessControlDescriptor) + desc.content_owner_id_count * sizeof(u64) + desc.save_data_owner_id_count * sizeof(u64)));
|
||||
if (data.save_data_owner_infos_size > 0) {
|
||||
/* Get the count. */
|
||||
const u32 num_save_data_owner_infos = util::LoadLittleEndian<u32>(reinterpret_cast<u32 *>(data_start + data.save_data_owner_infos_offset));
|
||||
|
||||
/* Get accessibility region.*/
|
||||
uintptr_t accessibility_start = data_start + data.save_data_owner_infos_offset + sizeof(u32);
|
||||
|
||||
/* Validate the id range. */
|
||||
uintptr_t id_start = accessibility_start + util::AlignUp(num_save_data_owner_infos * sizeof(Accessibility), alignof(u32));
|
||||
uintptr_t id_end = id_start + sizeof(u64) * num_save_data_owner_infos;
|
||||
AMS_ABORT_UNLESS(id_end == data_start + data.save_data_owner_infos_offset + data.save_data_owner_infos_size);
|
||||
|
||||
for (u32 i = 0; i < num_save_data_owner_infos; ++i) {
|
||||
/* Read the accessibility/id. */
|
||||
static_assert(sizeof(Accessibility) == 1);
|
||||
const Accessibility accessibility = *reinterpret_cast<Accessibility *>(accessibility_start + i * sizeof(Accessibility));
|
||||
const u64 id = util::LoadLittleEndian<u64>(reinterpret_cast<u64 *>(id_start + i * sizeof(u64)));
|
||||
|
||||
/* Check that the descriptor allows it. */
|
||||
bool allowed = false;
|
||||
if (desc.save_data_owner_id_count != 0) {
|
||||
for (u8 n = 0; n < desc.save_data_owner_id_count; ++n) {
|
||||
if (id == util::LoadLittleEndian<u64>(reinterpret_cast<u64 *>(desc_start + sizeof(AccessControlDescriptor) + desc.content_owner_id_count * sizeof(u64) + n * sizeof(u64)))) {
|
||||
allowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if ((desc.save_data_owner_id_min == 0 && desc.save_data_owner_id_max == 0) || (desc.save_data_owner_id_min <= id && id <= desc.save_data_owner_id_max)) {
|
||||
allowed = true;
|
||||
}
|
||||
|
||||
/* If the id is allowed, create it. */
|
||||
if (allowed) {
|
||||
if (auto *info = new SaveDataOwnerInfo(id, accessibility); info != nullptr) {
|
||||
m_save_data_owner_infos.push_front(*info);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
AccessControl::~AccessControl() {
|
||||
/* Delete all content owner infos. */
|
||||
while (!m_content_owner_infos.empty()) {
|
||||
auto *info = std::addressof(*m_content_owner_infos.rbegin());
|
||||
m_content_owner_infos.erase(m_content_owner_infos.iterator_to(*info));
|
||||
delete info;
|
||||
}
|
||||
|
||||
/* Delete all save data owner infos. */
|
||||
while (!m_save_data_owner_infos.empty()) {
|
||||
auto *info = std::addressof(*m_save_data_owner_infos.rbegin());
|
||||
m_save_data_owner_infos.erase(m_save_data_owner_infos.iterator_to(*info));
|
||||
delete info;
|
||||
}
|
||||
}
|
||||
|
||||
bool AccessControl::HasContentOwnerId(u64 owner_id) const {
|
||||
/* Check if we have a matching id. */
|
||||
for (const auto &info : m_content_owner_infos) {
|
||||
if (info.GetId() == owner_id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Accessibility AccessControl::GetAccessibilitySaveDataOwnedBy(u64 owner_id) const {
|
||||
/* Find a matching save data owner. */
|
||||
for (const auto &info : m_save_data_owner_infos) {
|
||||
if (info.GetId() == owner_id) {
|
||||
return info.GetAccessibility();
|
||||
}
|
||||
}
|
||||
|
||||
/* Default to no accessibility. */
|
||||
return Accessibility::MakeAccessibility(false, false);
|
||||
}
|
||||
|
||||
void AccessControl::ListContentOwnerId(s32 *out_count, u64 *out_owner_ids, s32 offset, s32 count) const {
|
||||
/* If we have nothing to read, just give the count. */
|
||||
if (count == 0) {
|
||||
*out_count = m_content_owner_infos.size();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read out the ids. */
|
||||
s32 read_offset = 0;
|
||||
s32 read_count = 0;
|
||||
if (out_owner_ids != nullptr) {
|
||||
auto *cur_out = out_owner_ids;
|
||||
for (const auto &info : m_content_owner_infos) {
|
||||
/* Skip until we get to the desired offset. */
|
||||
if (read_offset < offset) {
|
||||
++read_offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the output value. */
|
||||
*cur_out = info.GetId();
|
||||
++cur_out;
|
||||
++read_count;
|
||||
|
||||
/* If we've read as many as we can, finish. */
|
||||
if (read_count == count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the out value. */
|
||||
*out_count = read_count;
|
||||
}
|
||||
|
||||
void AccessControl::ListSaveDataOwnedId(s32 *out_count, ncm::ApplicationId *out_owner_ids, s32 offset, s32 count) const {
|
||||
/* If we have nothing to read, just give the count. */
|
||||
if (count == 0) {
|
||||
*out_count = m_save_data_owner_infos.size();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Read out the ids. */
|
||||
s32 read_offset = 0;
|
||||
s32 read_count = 0;
|
||||
if (out_owner_ids != nullptr) {
|
||||
auto *cur_out = out_owner_ids;
|
||||
for (const auto &info : m_save_data_owner_infos) {
|
||||
/* Skip until we get to the desired offset. */
|
||||
if (read_offset < offset) {
|
||||
++read_offset;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Set the output value. */
|
||||
cur_out->value = info.GetId();
|
||||
++cur_out;
|
||||
++read_count;
|
||||
|
||||
/* If we've read as many as we can, finish. */
|
||||
if (read_count == count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the out value. */
|
||||
*out_count = read_count;
|
||||
}
|
||||
|
||||
Accessibility AccessControl::GetAccessibilityFor(AccessibilityType type) const {
|
||||
switch (type) {
|
||||
using enum AccessibilityType;
|
||||
case MountLogo: return Accessibility::MakeAccessibility(m_flag_bits->CanMountLogoRead(), false);
|
||||
case MountContentMeta: return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentMetaRead(), false);
|
||||
case MountContentControl: return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentControlRead(), false);
|
||||
case MountContentManual: return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentManualRead(), false);
|
||||
case MountContentData: return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentDataRead(), false);
|
||||
case MountApplicationPackage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountApplicationPackageRead(), false);
|
||||
case MountSaveDataStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountSaveDataStorageRead(), m_flag_bits->CanMountSaveDataStorageWrite());
|
||||
case MountContentStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountContentStorageRead(), m_flag_bits->CanMountContentStorageWrite());
|
||||
case MountImageAndVideoStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountImageAndVideoStorageRead(), m_flag_bits->CanMountImageAndVideoStorageWrite());
|
||||
case MountCloudBackupWorkStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountCloudBackupWorkStorageRead(), m_flag_bits->CanMountCloudBackupWorkStorageWrite());
|
||||
case MountCustomStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanMountCustomStorage0Read(), m_flag_bits->CanMountCustomStorage0Write());
|
||||
case MountBisCalibrationFile: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisCalibrationFileRead(), m_flag_bits->CanMountBisCalibrationFileWrite());
|
||||
case MountBisSafeMode: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSafeModeRead(), m_flag_bits->CanMountBisSafeModeWrite());
|
||||
case MountBisUser: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisUserRead(), m_flag_bits->CanMountBisUserWrite());
|
||||
case MountBisSystem: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSystemRead(), m_flag_bits->CanMountBisSystemWrite());
|
||||
case MountBisSystemProperEncryption: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSystemProperEncryptionRead(), m_flag_bits->CanMountBisSystemProperEncryptionWrite());
|
||||
case MountBisSystemProperPartition: return Accessibility::MakeAccessibility(m_flag_bits->CanMountBisSystemProperPartitionRead(), m_flag_bits->CanMountBisSystemProperPartitionWrite());
|
||||
case MountSdCard: return Accessibility::MakeAccessibility(m_flag_bits->CanMountSdCardRead(), m_flag_bits->CanMountSdCardWrite());
|
||||
case MountGameCard: return Accessibility::MakeAccessibility(m_flag_bits->CanMountGameCardRead(), false);
|
||||
case MountDeviceSaveData: return Accessibility::MakeAccessibility(m_flag_bits->CanMountDeviceSaveDataRead(), m_flag_bits->CanMountDeviceSaveDataWrite());
|
||||
case MountSystemSaveData: return Accessibility::MakeAccessibility(m_flag_bits->CanMountSystemSaveDataRead(), m_flag_bits->CanMountSystemSaveDataWrite());
|
||||
case MountOthersSaveData: return Accessibility::MakeAccessibility(m_flag_bits->CanMountOthersSaveDataRead(), m_flag_bits->CanMountOthersSaveDataWrite());
|
||||
case MountOthersSystemSaveData: return Accessibility::MakeAccessibility(m_flag_bits->CanMountOthersSystemSaveDataRead(), m_flag_bits->CanMountOthersSystemSaveDataWrite());
|
||||
case OpenBisPartitionBootPartition1Root: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootPartition1RootRead(), m_flag_bits->CanOpenBisPartitionBootPartition1RootWrite());
|
||||
case OpenBisPartitionBootPartition2Root: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootPartition2RootRead(), m_flag_bits->CanOpenBisPartitionBootPartition2RootWrite());
|
||||
case OpenBisPartitionUserDataRoot: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionUserDataRootRead(), m_flag_bits->CanOpenBisPartitionUserDataRootWrite());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part1: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part1Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part1Write());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part2: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part2Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part2Write());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part3: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part3Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part3Write());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part4: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part4Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part4Write());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part5: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part5Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part5Write());
|
||||
case OpenBisPartitionBootConfigAndPackage2Part6: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part6Read(), m_flag_bits->CanOpenBisPartitionBootConfigAndPackage2Part6Write());
|
||||
case OpenBisPartitionCalibrationBinary: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionCalibrationBinaryRead(), m_flag_bits->CanOpenBisPartitionCalibrationBinaryWrite());
|
||||
case OpenBisPartitionCalibrationFile: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionCalibrationFileRead(), m_flag_bits->CanOpenBisPartitionCalibrationFileWrite());
|
||||
case OpenBisPartitionSafeMode: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSafeModeRead(), m_flag_bits->CanOpenBisPartitionSafeModeWrite());
|
||||
case OpenBisPartitionUser: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionUserRead(), m_flag_bits->CanOpenBisPartitionUserWrite());
|
||||
case OpenBisPartitionSystem: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSystemRead(), m_flag_bits->CanOpenBisPartitionSystemWrite());
|
||||
case OpenBisPartitionSystemProperEncryption: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSystemProperEncryptionRead(), m_flag_bits->CanOpenBisPartitionSystemProperEncryptionWrite());
|
||||
case OpenBisPartitionSystemProperPartition: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenBisPartitionSystemProperPartitionRead(), m_flag_bits->CanOpenBisPartitionSystemProperPartitionWrite());
|
||||
case OpenSdCardStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenSdCardStorageRead(), m_flag_bits->CanOpenSdCardStorageWrite());
|
||||
case OpenGameCardStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenGameCardStorageRead(), m_flag_bits->CanOpenGameCardStorageWrite());
|
||||
case MountSystemDataPrivate: return Accessibility::MakeAccessibility(m_flag_bits->CanMountSystemDataPrivateRead(), false);
|
||||
case MountHost: return Accessibility::MakeAccessibility(m_flag_bits->CanMountHostRead(), m_flag_bits->CanMountHostWrite());
|
||||
case MountRegisteredUpdatePartition: return Accessibility::MakeAccessibility(m_flag_bits->CanMountRegisteredUpdatePartitionRead() && g_is_debug_flag_enabled, false);
|
||||
case MountSaveDataInternalStorage: return Accessibility::MakeAccessibility(m_flag_bits->CanOpenSaveDataInternalStorageRead(), m_flag_bits->CanOpenSaveDataInternalStorageWrite());
|
||||
case MountTemporaryDirectory: return Accessibility::MakeAccessibility(m_flag_bits->CanMountTemporaryDirectoryRead(), m_flag_bits->CanMountTemporaryDirectoryWrite());
|
||||
case MountAllBaseFileSystem: return Accessibility::MakeAccessibility(m_flag_bits->CanMountAllBaseFileSystemRead(), m_flag_bits->CanMountAllBaseFileSystemWrite());
|
||||
case NotMount: return Accessibility::MakeAccessibility(false, false);
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
bool AccessControl::CanCall(OperationType type) const {
|
||||
switch (type) {
|
||||
using enum OperationType;
|
||||
case InvalidateBisCache: return m_flag_bits->CanInvalidateBisCache();
|
||||
case EraseMmc: return m_flag_bits->CanEraseMmc();
|
||||
case GetGameCardDeviceCertificate: return m_flag_bits->CanGetGameCardDeviceCertificate();
|
||||
case GetGameCardIdSet: return m_flag_bits->CanGetGameCardIdSet();
|
||||
case FinalizeGameCardDriver: return m_flag_bits->CanFinalizeGameCardDriver();
|
||||
case GetGameCardAsicInfo: return m_flag_bits->CanGetGameCardAsicInfo();
|
||||
case CreateSaveData: return m_flag_bits->CanCreateSaveData();
|
||||
case DeleteSaveData: return m_flag_bits->CanDeleteSaveData();
|
||||
case CreateSystemSaveData: return m_flag_bits->CanCreateSystemSaveData();
|
||||
case CreateOthersSystemSaveData: return m_flag_bits->CanCreateOthersSystemSaveData();
|
||||
case DeleteSystemSaveData: return m_flag_bits->CanDeleteSystemSaveData();
|
||||
case OpenSaveDataInfoReader: return m_flag_bits->CanOpenSaveDataInfoReader();
|
||||
case OpenSaveDataInfoReaderForSystem: return m_flag_bits->CanOpenSaveDataInfoReaderForSystem();
|
||||
case OpenSaveDataInfoReaderForInternal: return m_flag_bits->CanOpenSaveDataInfoReaderForInternal();
|
||||
case OpenSaveDataMetaFile: return m_flag_bits->CanOpenSaveDataMetaFile();
|
||||
case SetCurrentPosixTime: return m_flag_bits->CanSetCurrentPosixTime();
|
||||
case ReadSaveDataFileSystemExtraData: return m_flag_bits->CanReadSaveDataFileSystemExtraData();
|
||||
case SetGlobalAccessLogMode: return m_flag_bits->CanSetGlobalAccessLogMode();
|
||||
case SetSpeedEmulationMode: return m_flag_bits->CanSetSpeedEmulationMode();
|
||||
case FillBis: return m_flag_bits->CanFillBis();
|
||||
case CorruptSaveData: return m_flag_bits->CanCorruptSaveData();
|
||||
case CorruptSystemSaveData: return m_flag_bits->CanCorruptSystemSaveData();
|
||||
case VerifySaveData: return m_flag_bits->CanVerifySaveData();
|
||||
case DebugSaveData: return m_flag_bits->CanDebugSaveData();
|
||||
case FormatSdCard: return m_flag_bits->CanFormatSdCard();
|
||||
case GetRightsId: return m_flag_bits->CanGetRightsId();
|
||||
case RegisterExternalKey: return m_flag_bits->CanRegisterExternalKey();
|
||||
case SetEncryptionSeed: return m_flag_bits->CanSetEncryptionSeed();
|
||||
case WriteSaveDataFileSystemExtraDataTimeStamp: return m_flag_bits->CanWriteSaveDataFileSystemExtraDataTimeStamp();
|
||||
case WriteSaveDataFileSystemExtraDataFlags: return m_flag_bits->CanWriteSaveDataFileSystemExtraDataFlags();
|
||||
case WriteSaveDataFileSystemExtraDataCommitId: return m_flag_bits->CanWriteSaveDataFileSystemExtraDataCommitId();
|
||||
case WriteSaveDataFileSystemExtraDataAll: return m_flag_bits->CanWriteSaveDataFileSystemExtraDataAll();
|
||||
case ExtendSaveData: return m_flag_bits->CanExtendSaveData();
|
||||
case ExtendSystemSaveData: return m_flag_bits->CanExtendSystemSaveData();
|
||||
case ExtendOthersSystemSaveData: return m_flag_bits->CanExtendOthersSystemSaveData();
|
||||
case RegisterUpdatePartition: return m_flag_bits->CanRegisterUpdatePartition() && g_is_debug_flag_enabled;
|
||||
case OpenSaveDataTransferManager: return m_flag_bits->CanOpenSaveDataTransferManager();
|
||||
case OpenSaveDataTransferManagerVersion2: return m_flag_bits->CanOpenSaveDataTransferManagerVersion2();
|
||||
case OpenSaveDataTransferManagerForSaveDataRepair: return m_flag_bits->CanOpenSaveDataTransferManagerForSaveDataRepair();
|
||||
case OpenSaveDataTransferManagerForSaveDataRepairTool: return m_flag_bits->CanOpenSaveDataTransferManagerForSaveDataRepairTool();
|
||||
case OpenSaveDataTransferProhibiter: return m_flag_bits->CanOpenSaveDataTransferProhibiter();
|
||||
case OpenSaveDataMover: return m_flag_bits->CanOpenSaveDataMover();
|
||||
case OpenBisWiper: return m_flag_bits->CanOpenBisWiper();
|
||||
case ListAccessibleSaveDataOwnerId: return m_flag_bits->CanListAccessibleSaveDataOwnerId();
|
||||
case ControlMmcPatrol: return m_flag_bits->CanControlMmcPatrol();
|
||||
case OverrideSaveDataTransferTokenSignVerificationKey: return m_flag_bits->CanOverrideSaveDataTransferTokenSignVerificationKey();
|
||||
case OpenSdCardDetectionEventNotifier: return m_flag_bits->CanOpenSdCardDetectionEventNotifier();
|
||||
case OpenGameCardDetectionEventNotifier: return m_flag_bits->CanOpenGameCardDetectionEventNotifier();
|
||||
case OpenSystemDataUpdateEventNotifier: return m_flag_bits->CanOpenSystemDataUpdateEventNotifier();
|
||||
case NotifySystemDataUpdateEvent: return m_flag_bits->CanNotifySystemDataUpdateEvent();
|
||||
case OpenAccessFailureDetectionEventNotifier: return m_flag_bits->CanOpenAccessFailureDetectionEventNotifier();
|
||||
case GetAccessFailureDetectionEvent: return m_flag_bits->CanGetAccessFailureDetectionEvent();
|
||||
case IsAccessFailureDetected: return m_flag_bits->CanIsAccessFailureDetected();
|
||||
case ResolveAccessFailure: return m_flag_bits->CanResolveAccessFailure();
|
||||
case AbandonAccessFailure: return m_flag_bits->CanAbandonAccessFailure();
|
||||
case QuerySaveDataInternalStorageTotalSize: return m_flag_bits->CanQuerySaveDataInternalStorageTotalSize();
|
||||
case GetSaveDataCommitId: return m_flag_bits->CanGetSaveDataCommitId();
|
||||
case SetSdCardAccessibility: return m_flag_bits->CanSetSdCardAccessibility();
|
||||
case SimulateDevice: return m_flag_bits->CanSimulateDevice();
|
||||
case CreateSaveDataWithHashSalt: return m_flag_bits->CanCreateSaveDataWithHashSalt();
|
||||
case RegisterProgramIndexMapInfo: return m_flag_bits->CanRegisterProgramIndexMapInfo();
|
||||
case ChallengeCardExistence: return m_flag_bits->CanChallengeCardExistence();
|
||||
case CreateOwnSaveData: return m_flag_bits->CanCreateOwnSaveData();
|
||||
case DeleteOwnSaveData: return m_flag_bits->CanDeleteOwnSaveData();
|
||||
case ReadOwnSaveDataFileSystemExtraData: return m_flag_bits->CanReadOwnSaveDataFileSystemExtraData();
|
||||
case ExtendOwnSaveData: return m_flag_bits->CanExtendOwnSaveData();
|
||||
case OpenOwnSaveDataTransferProhibiter: return m_flag_bits->CanOpenOwnSaveDataTransferProhibiter();
|
||||
case FindOwnSaveDataWithFilter: return m_flag_bits->CanFindOwnSaveDataWithFilter();
|
||||
case OpenSaveDataTransferManagerForRepair: return m_flag_bits->CanOpenSaveDataTransferManagerForRepair();
|
||||
case SetDebugConfiguration: return m_flag_bits->CanSetDebugConfiguration();
|
||||
case OpenDataStorageByPath: return m_flag_bits->CanOpenDataStorageByPath();
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
using NotifyProcessDeferredFunction = void (*)(u64 process_id);
|
||||
|
||||
struct DeferredProcessEntryForDeviceError : public util::IntrusiveListBaseNode<DeferredProcessEntryForDeviceError>, public fs::impl::Newable {
|
||||
os::MultiWaitHolderType *process_holder;
|
||||
u64 process_id;
|
||||
};
|
||||
|
||||
class DeferredProcessQueueForDeviceError {
|
||||
NON_COPYABLE(DeferredProcessQueueForDeviceError);
|
||||
NON_MOVEABLE(DeferredProcessQueueForDeviceError);
|
||||
private:
|
||||
using EntryList = util::IntrusiveListBaseTraits<DeferredProcessEntryForDeviceError>::ListType;
|
||||
private:
|
||||
EntryList m_list{};
|
||||
os::SdkMutex m_mutex{};
|
||||
public:
|
||||
constexpr DeferredProcessQueueForDeviceError() = default;
|
||||
};
|
||||
|
||||
class DeferredProcessEntryForPriority : public util::IntrusiveListBaseNode<DeferredProcessEntryForPriority>, public fs::impl::Newable {
|
||||
private:
|
||||
os::MultiWaitHolderType *m_process_holder;
|
||||
FileSystemProxyServerSessionType m_session_type;
|
||||
};
|
||||
|
||||
class DeferredProcessQueueForPriority {
|
||||
NON_COPYABLE(DeferredProcessQueueForPriority);
|
||||
NON_MOVEABLE(DeferredProcessQueueForPriority);
|
||||
private:
|
||||
using EntryList = util::IntrusiveListBaseTraits<DeferredProcessEntryForPriority>::ListType;
|
||||
private:
|
||||
EntryList m_list{};
|
||||
os::SdkRecursiveMutex m_mutex{};
|
||||
os::SdkConditionVariable m_cv{};
|
||||
public:
|
||||
constexpr DeferredProcessQueueForPriority() = default;
|
||||
};
|
||||
|
||||
template<typename ServerManager, NotifyProcessDeferredFunction NotifyProcessDeferred>
|
||||
class DeferredProcessManager {
|
||||
NON_COPYABLE(DeferredProcessManager);
|
||||
NON_MOVEABLE(DeferredProcessManager);
|
||||
private:
|
||||
DeferredProcessQueueForDeviceError m_queue_for_device_error{};
|
||||
os::SdkMutex m_invoke_mutex_for_device_error{};
|
||||
DeferredProcessQueueForPriority m_queue_for_priority{};
|
||||
std::atomic_bool m_is_invoke_deferred_process_event_linked{};
|
||||
os::EventType m_invoke_event{};
|
||||
os::MultiWaitHolderType m_invoke_event_holder{};
|
||||
bool m_initialized{false};
|
||||
public:
|
||||
constexpr DeferredProcessManager() = default;
|
||||
|
||||
void Initialize() {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(!m_initialized);
|
||||
os::InitializeEvent(std::addressof(m_invoke_event), false, os::EventClearMode_ManualClear);
|
||||
os::InitializeMultiWaitHolder(std::addressof(m_invoke_event_holder), std::addressof(m_invoke_event));
|
||||
m_initialized = true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <stratosphere/fs/impl/fs_service_name.hpp>
|
||||
#include "fssrv_deferred_process_manager.hpp"
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
namespace {
|
||||
|
||||
struct FileSystemProxyServerOptions {
|
||||
static constexpr size_t PointerBufferSize = 0x800;
|
||||
static constexpr size_t MaxDomains = 0x40;
|
||||
static constexpr size_t MaxDomainObjects = 0x4000;
|
||||
static constexpr bool CanDeferInvokeRequest = true;
|
||||
static constexpr bool CanManageMitmServers = false;
|
||||
};
|
||||
|
||||
enum PortIndex {
|
||||
PortIndex_FileSystemProxy,
|
||||
PortIndex_ProgramRegistry,
|
||||
PortIndex_FileSystemProxyForLoader,
|
||||
PortIndex_Count,
|
||||
};
|
||||
|
||||
constexpr size_t FileSystemProxyMaxSessions = 59;
|
||||
constexpr size_t ProgramRegistryMaxSessions = 1;
|
||||
constexpr size_t FileSystemProxyForLoaderMaxSessions = 1;
|
||||
|
||||
constexpr size_t NumSessions = FileSystemProxyMaxSessions + ProgramRegistryMaxSessions + FileSystemProxyForLoaderMaxSessions;
|
||||
|
||||
constinit os::SemaphoreType g_semaphore_for_file_system_proxy_for_loader = {};
|
||||
constinit os::SemaphoreType g_semaphore_for_program_registry = {};
|
||||
|
||||
class FileSystemProxyServerManager final : public ams::sf::hipc::ServerManager<PortIndex_Count, FileSystemProxyServerOptions, NumSessions> {
|
||||
private:
|
||||
virtual ams::Result OnNeedsToAccept(int port_index, Server *server) override {
|
||||
switch (port_index) {
|
||||
case PortIndex_FileSystemProxy:
|
||||
{
|
||||
R_RETURN(this->AcceptImpl(server, impl::GetFileSystemProxyServiceObject()));
|
||||
}
|
||||
case PortIndex_ProgramRegistry:
|
||||
{
|
||||
if (os::TryAcquireSemaphore(std::addressof(g_semaphore_for_program_registry))) {
|
||||
ON_RESULT_FAILURE { os::ReleaseSemaphore(std::addressof(g_semaphore_for_program_registry)); };
|
||||
|
||||
R_RETURN(this->AcceptImpl(server, impl::GetProgramRegistryServiceObject()));
|
||||
} else {
|
||||
R_RETURN(this->AcceptImpl(server, impl::GetInvalidProgramRegistryServiceObject()));
|
||||
}
|
||||
}
|
||||
case PortIndex_FileSystemProxyForLoader:
|
||||
{
|
||||
if (os::TryAcquireSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader))) {
|
||||
ON_RESULT_FAILURE { os::ReleaseSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader)); };
|
||||
|
||||
R_RETURN(this->AcceptImpl(server, impl::GetFileSystemProxyForLoaderServiceObject()));
|
||||
} else {
|
||||
R_RETURN(this->AcceptImpl(server, impl::GetInvalidFileSystemProxyForLoaderServiceObject()));
|
||||
}
|
||||
}
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
constinit util::TypedStorage<FileSystemProxyServerManager> g_server_manager_storage = {};
|
||||
constinit FileSystemProxyServerManager *g_server_manager = nullptr;
|
||||
|
||||
constinit os::BarrierType g_server_loop_barrier = {};
|
||||
constinit os::EventType g_resume_wait_event = {};
|
||||
|
||||
constinit bool g_is_suspended = false;
|
||||
|
||||
void TemporaryNotifyProcessDeferred(u64) { /* TODO */ }
|
||||
|
||||
constinit DeferredProcessManager<FileSystemProxyServerManager, TemporaryNotifyProcessDeferred> g_deferred_process_manager;
|
||||
|
||||
}
|
||||
|
||||
void InitializeForFileSystemProxy(const FileSystemProxyConfiguration &config) {
|
||||
/* TODO FS-REIMPL */
|
||||
AMS_UNUSED(config);
|
||||
}
|
||||
|
||||
void InitializeFileSystemProxyServer(int threads) {
|
||||
/* Initialize synchronization primitives. */
|
||||
os::InitializeBarrier(std::addressof(g_server_loop_barrier), threads + 1);
|
||||
os::InitializeEvent(std::addressof(g_resume_wait_event), false, os::EventClearMode_ManualClear);
|
||||
g_is_suspended = false;
|
||||
os::InitializeSemaphore(std::addressof(g_semaphore_for_file_system_proxy_for_loader), 1, 1);
|
||||
os::InitializeSemaphore(std::addressof(g_semaphore_for_program_registry), 1, 1);
|
||||
|
||||
/* Initialize deferred process manager. */
|
||||
g_deferred_process_manager.Initialize();
|
||||
|
||||
/* Create the server and register our services. */
|
||||
AMS_ASSERT(g_server_manager == nullptr);
|
||||
g_server_manager = util::ConstructAt(g_server_manager_storage);
|
||||
|
||||
/* TODO: Manager handler. */
|
||||
|
||||
R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_FileSystemProxy, fs::impl::FileSystemProxyServiceName, FileSystemProxyMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_ProgramRegistry, fs::impl::ProgramRegistryServiceName, ProgramRegistryMaxSessions));
|
||||
R_ABORT_UNLESS(g_server_manager->RegisterServer(PortIndex_FileSystemProxyForLoader, fs::impl::FileSystemProxyForLoaderServiceName, FileSystemProxyForLoaderMaxSessions));
|
||||
|
||||
/* Enable processing on server. */
|
||||
g_server_manager->ResumeProcessing();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,500 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <stratosphere/fssrv/fssrv_interface_adapters.hpp>
|
||||
#include "impl/fssrv_allocator_for_service_framework.hpp"
|
||||
#include "impl/fssrv_program_info.hpp"
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
FileSystemProxyImpl::FileSystemProxyImpl() {
|
||||
/* TODO: Set core impl. */
|
||||
m_process_id = os::InvalidProcessId.value;
|
||||
}
|
||||
|
||||
FileSystemProxyImpl::~FileSystemProxyImpl() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
Result FileSystemProxyImpl::OpenFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::FileSystemProxyImpl::SetCurrentProcess(const ams::sf::ClientProcessId &client_pid) {
|
||||
/* Set current process. */
|
||||
m_process_id = client_pid.GetValue().value;
|
||||
|
||||
/* TODO: Allocate NcaFileSystemService. */
|
||||
/* TODO: Allocate SaveDataFileSystemService. */
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataFileSystemByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenFileSystemWithPatch(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenFileSystemWithIdObsolete(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u64 program_id, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenFileSystemWithId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, fs::ContentAttributes attr, u64 program_id, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataFileSystemByProgramId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenBisFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenBisStorage(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::InvalidateBisCache() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenHostFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path) {
|
||||
/* Invoke the modern API from the legacy API. */
|
||||
R_RETURN(this->OpenHostFileSystemWithOption(out, path, fs::MountHostOption::None._value));
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenSdCardFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::FormatSdCardFileSystem() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::DeleteSaveDataFileSystem(u64 save_data_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::CreateSaveDataFileSystem(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::CreateSaveDataFileSystemBySystemSaveDataId(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::RegisterSaveDataFileSystemAtomicDeletion(const ams::sf::InBuffer &save_data_ids) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::DeleteSaveDataFileSystemBySaveDataSpaceId(u8 indexer_space_id, u64 save_data_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::FormatSdCardDryRun() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::IsExFatSupported(ams::sf::Out<bool> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::DeleteSaveDataFileSystemBySaveDataAttribute(u8 space_id, const fs::SaveDataAttribute &attribute) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenGameCardStorage(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u32 handle, u32 partition) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenGameCardFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 handle, u32 partition) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::ExtendSaveDataFileSystem(u8 space_id, u64 save_data_id, s64 available_size, s64 journal_size) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::DeleteCacheStorage(u16 index) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetCacheStorageSize(ams::sf::Out<s64> out_size, ams::sf::Out<s64> out_journal_size, u16 index) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::CreateSaveDataFileSystemWithHashSalt(const fs::SaveDataAttribute &attribute, const fs::SaveDataCreationInfo &creation_info, const fs::SaveDataMetaInfo &meta_info, const fs::HashSalt &salt) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenHostFileSystemWithOption(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, const fssrv::sf::FspPath &path, u32 _option) {
|
||||
/* TODO: GetProgramInfo */
|
||||
/* TODO: GetAccessibility. */
|
||||
/* TODO: Check Accessibility CanRead/CanWrite */
|
||||
|
||||
/* Convert the path. */
|
||||
fs::Path normalized_path;
|
||||
#if defined(ATMOSPHERE_OS_WINDOWS)
|
||||
R_TRY(normalized_path.Initialize(path.str));
|
||||
#else
|
||||
if (path.str[0] == '/' && path.str[1] == '/') {
|
||||
R_TRY(normalized_path.Initialize(path.str));
|
||||
} else {
|
||||
R_TRY(normalized_path.InitializeWithReplaceUnc(path.str));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Normalize the path. */
|
||||
fs::PathFlags path_flags;
|
||||
path_flags.AllowWindowsPath();
|
||||
path_flags.AllowRelativePath();
|
||||
path_flags.AllowEmptyPath();
|
||||
R_TRY(normalized_path.Normalize(path_flags));
|
||||
|
||||
/* Parse option. */
|
||||
const fs::MountHostOption option{ _option };
|
||||
|
||||
/* TODO: FileSystemProxyCoreImpl::OpenHostFileSystem */
|
||||
/* TODO: use creator interfaces */
|
||||
std::shared_ptr<fs::fsa::IFileSystem> fs;
|
||||
{
|
||||
fssrv::fscreator::LocalFileSystemCreator local_fs_creator(true);
|
||||
|
||||
R_TRY(static_cast<fscreator::ILocalFileSystemCreator &>(local_fs_creator).Create(std::addressof(fs), normalized_path, option.HasPseudoCaseSensitiveFlag()));
|
||||
}
|
||||
|
||||
/* Determine path flags for the result fs. */
|
||||
fs::PathFlags host_path_flags;
|
||||
if (path.str[0] == 0) {
|
||||
host_path_flags.AllowWindowsPath();
|
||||
}
|
||||
|
||||
/* Create an interface adapter. */
|
||||
auto sf_fs = impl::FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IFileSystem, impl::FileSystemInterfaceAdapter>(std::move(fs), host_path_flags, false);
|
||||
R_UNLESS(sf_fs != nullptr, fs::ResultAllocationMemoryFailedInFileSystemProxyImplA());
|
||||
|
||||
/* Set the output. */
|
||||
*out = std::move(sf_fs);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenSaveDataFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenSaveDataFileSystemBySystemSaveDataId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenReadOnlySaveDataFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 space_id, const fs::SaveDataAttribute &attribute) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::ReadSaveDataFileSystemExtraDataBySaveDataSpaceId(const ams::sf::OutBuffer &buffer, u8 space_id, u64 save_data_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::ReadSaveDataFileSystemExtraData(const ams::sf::OutBuffer &buffer, u64 save_data_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::WriteSaveDataFileSystemExtraData(u64 save_data_id, u8 space_id, const ams::sf::InBuffer &buffer) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::OpenImageDirectoryFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::OpenContentStorageFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u32 id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageByProgramId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageByDataId(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, ncm::DataId data_id, u8 storage_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenPatchDataStorageByCurrentProcess(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataFileSystemWithProgramIndex(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out, u8 index) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageWithProgramIndex(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, u8 index) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageByPathObsolete(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, const fssrv::sf::FspPath &path, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDataStorageByPath(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IStorage>> out, const fssrv::sf::FspPath &path, fs::ContentAttributes attr, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenDeviceOperator(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDeviceOperator>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenSdCardDetectionEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenGameCardDetectionEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenSystemDataUpdateEventNotifier(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IEventNotifier>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::NotifySystemDataUpdateEvent() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::SetCurrentPosixTime(s64 posix_time) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::GetRightsId(ams::sf::Out<fs::RightsId> out, ncm::ProgramId program_id, ncm::StorageId storage_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::RegisterExternalKey(const fs::RightsId &rights_id, const spl::AccessKey &access_key) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::UnregisterAllExternalKey() {
|
||||
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) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetRightsIdAndKeyGenerationByPathObsolete(ams::sf::Out<fs::RightsId> out, ams::sf::Out<u8> out_key_generation, const fssrv::sf::FspPath &path) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetRightsIdAndKeyGenerationByPath(ams::sf::Out<fs::RightsId> out, ams::sf::Out<u8> out_key_generation, const fssrv::sf::FspPath &path, fs::ContentAttributes attr) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetCurrentPosixTimeWithTimeDifference(s64 posix_time, s32 time_difference) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetFreeSpaceSizeForSaveData(ams::sf::Out<s64> out, u8 space_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::VerifySaveDataFileSystemBySaveDataSpaceId() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::CorruptSaveDataFileSystemBySaveDataSpaceId() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::QuerySaveDataInternalStorageTotalSize() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetSaveDataCommitId() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::UnregisterExternalKey(const fs::RightsId &rights_id) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetSdCardEncryptionSeed(const fs::EncryptionSeed &seed) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetSdCardAccessibility(bool accessible) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::IsSdCardAccessible(ams::sf::Out<bool> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::IsSignedSystemPartitionOnSdCardValid(ams::sf::Out<bool> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenAccessFailureDetectionEventNotifier() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::GetAndClearErrorInfo(ams::sf::Out<fs::FileSystemProxyErrorInfo> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::RegisterProgramIndexMapInfo(const ams::sf::InBuffer &buffer, s32 count) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetBisRootForHost(u32 id, const fssrv::sf::FspPath &path) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetSaveDataSize(s64 size, s64 journal_size) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetSaveDataRootPath(const fssrv::sf::FspPath &path) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::DisableAutoSaveDataCreation() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::SetGlobalAccessLogMode(u32 mode) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetGlobalAccessLogMode(ams::sf::Out<u32> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OutputAccessLogToSdCard(const ams::sf::InBuffer &buf) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::RegisterUpdatePartition() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenRegisteredUpdatePartition(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetAndClearMemoryReportInfo(ams::sf::Out<fs::MemoryReportInfo> out) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
Result FileSystemProxyImpl::GetProgramIndexForAccessLog(ams::sf::Out<u32> out_idx, ams::sf::Out<u32> out_count) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::GetFsStackUsage(ams::sf::Out<u32> out, u32 type) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::UnsetSaveDataRootPath() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OutputMultiProgramTagAccessLog() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::FlushAccessLogOnSdCard() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OutputApplicationInfoAccessLog() {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::RegisterDebugConfiguration(u32 key, s64 value) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::UnregisterDebugConfiguration(u32 key) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OverrideSaveDataTransferTokenSignVerificationKey(const ams::sf::InBuffer &buf) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::CorruptSaveDataFileSystemByOffset(u8 space_id, u64 save_data_id, s64 offset) {
|
||||
AMS_ABORT("TODO");
|
||||
}
|
||||
|
||||
/* ... */
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
Result FileSystemProxyImpl::OpenCodeFileSystemDeprecated(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, const fssrv::sf::Path &path, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out_fs, path, program_id);
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenCodeFileSystemDeprecated2(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, ams::sf::Out<fs::CodeVerificationData> out_verif, const fssrv::sf::Path &path, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out_fs, out_verif, path, program_id);
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenCodeFileSystemDeprecated3(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, ams::sf::Out<fs::CodeVerificationData> out_verif, const fssrv::sf::Path &path, fs::ContentAttributes attr, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out_fs, out_verif, path, attr, program_id);
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenCodeFileSystemDeprecated4(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, const ams::sf::OutBuffer &out_verif, const fssrv::sf::Path &path, fs::ContentAttributes attr, ncm::ProgramId program_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out_fs, out_verif, path, attr, program_id);
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::OpenCodeFileSystem(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFileSystem>> out_fs, const ams::sf::OutBuffer &out_verif, fs::ContentAttributes attr, ncm::ProgramId program_id, ncm::StorageId storage_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out_fs, out_verif, attr, program_id, storage_id);
|
||||
}
|
||||
|
||||
Result FileSystemProxyImpl::IsArchivedProgram(ams::sf::Out<bool> out, u64 process_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(out, process_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,379 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <stratosphere/fssrv/fssrv_interface_adapters.hpp>
|
||||
#include "impl/fssrv_allocator_for_service_framework.hpp"
|
||||
#include "fssrv_retry_utility.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr const char *RootDirectory = "/";
|
||||
|
||||
}
|
||||
|
||||
FileInterfaceAdapter::FileInterfaceAdapter(std::unique_ptr<fs::fsa::IFile> &&file, FileSystemInterfaceAdapter *parent, bool allow_all)
|
||||
: m_parent_filesystem(parent, true), m_base_file(std::move(file)), m_allow_all_operations(allow_all)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::Read(ams::sf::Out<s64> out, s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size, fs::ReadOption option) {
|
||||
/* Check pre-conditions. */
|
||||
R_UNLESS(0 <= offset, fs::ResultInvalidOffset());
|
||||
R_UNLESS(0 <= size, fs::ResultInvalidSize());
|
||||
R_UNLESS(size <= static_cast<s64>(buffer.GetSize()), fs::ResultInvalidSize());
|
||||
|
||||
/* Read the data, retrying on corruption. */
|
||||
size_t read_size = 0;
|
||||
R_TRY(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_file->Read(std::addressof(read_size), offset, buffer.GetPointer(), static_cast<size_t>(size), option));
|
||||
}));
|
||||
|
||||
/* Set the output size. */
|
||||
*out = read_size;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size, fs::WriteOption option) {
|
||||
/* Check pre-conditions. */
|
||||
R_UNLESS(0 <= offset, fs::ResultInvalidOffset());
|
||||
R_UNLESS(0 <= size, fs::ResultInvalidSize());
|
||||
R_UNLESS(size <= static_cast<s64>(buffer.GetSize()), fs::ResultInvalidSize());
|
||||
|
||||
/* Temporarily increase our thread's priority. */
|
||||
fssystem::ScopedThreadPriorityChangerByAccessPriority cp(fssystem::ScopedThreadPriorityChangerByAccessPriority::AccessMode::Write);
|
||||
|
||||
R_RETURN(m_base_file->Write(offset, buffer.GetPointer(), size, option));
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::Flush() {
|
||||
R_RETURN(m_base_file->Flush());
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::SetSize(s64 size) {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
R_RETURN(m_base_file->SetSize(size));
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::GetSize(ams::sf::Out<s64> out) {
|
||||
/* Get the size, retrying on corruption. */
|
||||
R_RETURN(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_file->GetSize(out.GetPointer()));
|
||||
}));
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::OperateRange(ams::sf::Out<fs::FileQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
|
||||
/* N includes this redundant check, so we will too. */
|
||||
R_UNLESS(out.GetPointer() != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Clear the range info. */
|
||||
out->Clear();
|
||||
|
||||
if (op_id == static_cast<s32>(fs::OperationId::QueryRange)) {
|
||||
fs::FileQueryRangeInfo info;
|
||||
R_TRY(m_base_file->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
out->Merge(info);
|
||||
} else if (op_id == static_cast<s32>(fs::OperationId::Invalidate)) {
|
||||
R_TRY(m_base_file->OperateRange(nullptr, 0, fs::OperationId::Invalidate, offset, size, nullptr, 0));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileInterfaceAdapter::OperateRangeWithBuffer(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 op_id, s64 offset, s64 size) {
|
||||
/* Check that we have permission to perform the operation. */
|
||||
switch (static_cast<fs::OperationId>(op_id)) {
|
||||
using enum fs::OperationId;
|
||||
case QueryUnpreparedRange:
|
||||
case QueryLazyLoadCompletionRate:
|
||||
case SetLazyLoadPriority:
|
||||
/* Lazy load/unprepared operations are always allowed to be performed with buffer. */
|
||||
break;
|
||||
default:
|
||||
R_UNLESS(m_allow_all_operations, fs::ResultPermissionDenied());
|
||||
}
|
||||
|
||||
/* Perform the operation. */
|
||||
R_RETURN(m_base_file->OperateRange(out_buf.GetPointer(), out_buf.GetSize(), static_cast<fs::OperationId>(op_id), offset, size, in_buf.GetPointer(), in_buf.GetSize()));
|
||||
}
|
||||
|
||||
DirectoryInterfaceAdapter::DirectoryInterfaceAdapter(std::unique_ptr<fs::fsa::IDirectory> &&dir, FileSystemInterfaceAdapter *parent, bool allow_all)
|
||||
: m_parent_filesystem(parent, true), m_base_dir(std::move(dir)), m_allow_all_operations(allow_all)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
Result DirectoryInterfaceAdapter::Read(ams::sf::Out<s64> out, const ams::sf::OutBuffer &out_entries) {
|
||||
/* Get the maximum number of entries we can read into the buffer. */
|
||||
const s64 max_num_entries = out_entries.GetSize() / sizeof(fs::DirectoryEntry);
|
||||
R_UNLESS(max_num_entries >= 0, fs::ResultInvalidSize());
|
||||
|
||||
/* Get the size, retrying on corruption. */
|
||||
s64 num_read = 0;
|
||||
R_TRY(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_dir->Read(std::addressof(num_read), reinterpret_cast<fs::DirectoryEntry *>(out_entries.GetPointer()), max_num_entries));
|
||||
}));
|
||||
|
||||
/* Set the output. */
|
||||
*out = num_read;
|
||||
R_SUCCEED();
|
||||
|
||||
}
|
||||
|
||||
Result DirectoryInterfaceAdapter::GetEntryCount(ams::sf::Out<s64> out) {
|
||||
R_RETURN(m_base_dir->GetEntryCount(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::SetUpPath(fs::Path *out, const fssrv::sf::Path &sf_path) {
|
||||
/* Initialize the fs path. */
|
||||
if (m_path_flags.IsWindowsPathAllowed()) {
|
||||
R_TRY(out->InitializeWithReplaceUnc(sf_path.str));
|
||||
} else {
|
||||
R_TRY(out->Initialize(sf_path.str));
|
||||
}
|
||||
|
||||
/* Ensure the path is normalized. */
|
||||
R_RETURN(out->Normalize(m_path_flags));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CreateFile(const fssrv::sf::Path &path, s64 size, s32 option) {
|
||||
/* Check pre-conditions. */
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->CreateFile(fs_path, size, option));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteFile(const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->DeleteFile(fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CreateDirectory(const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
/* Sanity check that the directory isn't the root. */
|
||||
R_UNLESS(fs_path != RootDirectory, fs::ResultPathAlreadyExists());
|
||||
|
||||
R_RETURN(m_base_fs->CreateDirectory(fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteDirectory(const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
/* Sanity check that the directory isn't the root. */
|
||||
R_UNLESS(fs_path != RootDirectory, fs::ResultDirectoryNotDeletable());
|
||||
|
||||
R_RETURN(m_base_fs->DeleteDirectory(fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::DeleteDirectoryRecursively(const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
/* Sanity check that the directory isn't the root. */
|
||||
R_UNLESS(fs_path != RootDirectory, fs::ResultDirectoryNotDeletable());
|
||||
|
||||
R_RETURN(m_base_fs->DeleteDirectoryRecursively(fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::RenameFile(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
|
||||
/* Normalize the input paths. */
|
||||
fs::Path fs_old_path;
|
||||
fs::Path fs_new_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_old_path), old_path));
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_new_path), new_path));
|
||||
|
||||
R_RETURN(m_base_fs->RenameFile(fs_old_path, fs_new_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::RenameDirectory(const fssrv::sf::Path &old_path, const fssrv::sf::Path &new_path) {
|
||||
/* Normalize the input paths. */
|
||||
fs::Path fs_old_path;
|
||||
fs::Path fs_new_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_old_path), old_path));
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_new_path), new_path));
|
||||
|
||||
R_UNLESS(!fs::IsSubPath(fs_old_path.GetString(), fs_new_path.GetString()), fs::ResultDirectoryNotRenamable());
|
||||
|
||||
R_RETURN(m_base_fs->RenameDirectory(fs_old_path, fs_new_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetEntryType(ams::sf::Out<u32> out, const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
static_assert(sizeof(*out.GetPointer()) == sizeof(fs::DirectoryEntryType));
|
||||
R_RETURN(m_base_fs->GetEntryType(reinterpret_cast<fs::DirectoryEntryType *>(out.GetPointer()), fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::OpenFile(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFile>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
/* Open the file, retrying on corruption. */
|
||||
std::unique_ptr<fs::fsa::IFile> file;
|
||||
R_TRY(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_fs->OpenFile(std::addressof(file), fs_path, static_cast<fs::OpenMode>(mode)));
|
||||
}));
|
||||
|
||||
/* If we're a mitm interface, we should preserve the resulting target object id. */
|
||||
if (m_is_mitm_interface) {
|
||||
/* TODO: This is a hack to get the mitm API to work. Better solution? */
|
||||
const auto target_object_id = file->GetDomainObjectId();
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IFile> file_intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IFile, FileInterfaceAdapter>(std::move(file), this, m_allow_all_operations);
|
||||
R_UNLESS(file_intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(file_intf), target_object_id);
|
||||
} else {
|
||||
ams::sf::SharedPointer<fssrv::sf::IFile> file_intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IFile, FileInterfaceAdapter>(std::move(file), this, m_allow_all_operations);
|
||||
R_UNLESS(file_intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(file_intf));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::OpenDirectory(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDirectory>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
/* Open the directory, retrying on corruption. */
|
||||
std::unique_ptr<fs::fsa::IDirectory> dir;
|
||||
R_TRY(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_fs->OpenDirectory(std::addressof(dir), fs_path, static_cast<fs::OpenDirectoryMode>(mode)));
|
||||
}));
|
||||
|
||||
/* If we're a mitm interface, we should preserve the resulting target object id. */
|
||||
if (m_is_mitm_interface) {
|
||||
/* TODO: This is a hack to get the mitm API to work. Better solution? */
|
||||
const auto target_object_id = dir->GetDomainObjectId();
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IDirectory> dir_intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IDirectory, DirectoryInterfaceAdapter>(std::move(dir), this, m_allow_all_operations);
|
||||
R_UNLESS(dir_intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(dir_intf), target_object_id);
|
||||
} else {
|
||||
ams::sf::SharedPointer<fssrv::sf::IDirectory> dir_intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IDirectory, DirectoryInterfaceAdapter>(std::move(dir), this, m_allow_all_operations);
|
||||
R_UNLESS(dir_intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(dir_intf));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::Commit() {
|
||||
R_RETURN(m_base_fs->Commit());
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetFreeSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->GetFreeSpaceSize(out.GetPointer(), fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetTotalSpaceSize(ams::sf::Out<s64> out, const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->GetTotalSpaceSize(out.GetPointer(), fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::CleanDirectoryRecursively(const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->CleanDirectoryRecursively(fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::GetFileTimeStampRaw(ams::sf::Out<fs::FileTimeStampRaw> out, const fssrv::sf::Path &path) {
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
R_RETURN(m_base_fs->GetFileTimeStampRaw(out.GetPointer(), fs_path));
|
||||
}
|
||||
|
||||
Result FileSystemInterfaceAdapter::QueryEntry(const ams::sf::OutNonSecureBuffer &out_buf, const ams::sf::InNonSecureBuffer &in_buf, s32 query_id, const fssrv::sf::Path &path) {
|
||||
/* Check that we have permission to perform the operation. */
|
||||
switch (static_cast<fs::fsa::QueryId>(query_id)) {
|
||||
using enum fs::fsa::QueryId;
|
||||
case SetConcatenationFileAttribute:
|
||||
case IsSignedSystemPartitionOnSdCardValid:
|
||||
case QueryUnpreparedFileInformation:
|
||||
/* Only certain operations are unconditionally allowable. */
|
||||
break;
|
||||
default:
|
||||
R_UNLESS(m_allow_all_operations, fs::ResultPermissionDenied());
|
||||
}
|
||||
|
||||
/* Normalize the input path. */
|
||||
fs::Path fs_path;
|
||||
R_TRY(this->SetUpPath(std::addressof(fs_path), path));
|
||||
|
||||
char *dst = reinterpret_cast<char *>(out_buf.GetPointer());
|
||||
const char *src = reinterpret_cast<const char *>(in_buf.GetPointer());
|
||||
R_RETURN(m_base_fs->QueryEntry(dst, out_buf.GetSize(), src, in_buf.GetSize(), static_cast<fs::fsa::QueryId>(query_id), fs_path));
|
||||
}
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
Result RemoteFileSystem::OpenFile(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IFile>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
FsFile f;
|
||||
R_TRY(fsFsOpenFile(std::addressof(m_base_fs), path.str, mode, std::addressof(f)));
|
||||
|
||||
auto intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IFile, RemoteFile>(f);
|
||||
R_UNLESS(intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(intf));
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result RemoteFileSystem::OpenDirectory(ams::sf::Out<ams::sf::SharedPointer<fssrv::sf::IDirectory>> out, const fssrv::sf::Path &path, u32 mode) {
|
||||
FsDir d;
|
||||
R_TRY(fsFsOpenDirectory(std::addressof(m_base_fs), path.str, mode, std::addressof(d)));
|
||||
|
||||
auto intf = FileSystemObjectFactory::CreateSharedEmplaced<fssrv::sf::IDirectory, RemoteDirectory>(d);
|
||||
R_UNLESS(intf != nullptr, fs::ResultAllocationMemoryFailedInFileSystemInterfaceAdapterA());
|
||||
|
||||
out.SetValue(std::move(intf));
|
||||
R_SUCCEED();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
namespace {
|
||||
|
||||
size_t GetUsedSize(void *p) {
|
||||
const auto block_head = reinterpret_cast<const lmem::impl::ExpHeapMemoryBlockHead *>(reinterpret_cast<uintptr_t>(p) - sizeof(lmem::impl::ExpHeapMemoryBlockHead));
|
||||
return block_head->block_size + ((block_head->attributes >> 8) & 0x7F) + sizeof(lmem::impl::ExpHeapMemoryBlockHead);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PeakCheckableMemoryResourceFromExpHeap::OnAllocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
if (p != nullptr) {
|
||||
m_current_free_size = GetUsedSize(p);
|
||||
m_peak_free_size = std::min(m_peak_free_size, m_current_free_size);
|
||||
}
|
||||
}
|
||||
|
||||
void PeakCheckableMemoryResourceFromExpHeap::OnDeallocate(void *p, size_t size) {
|
||||
AMS_UNUSED(size);
|
||||
|
||||
if (p != nullptr) {
|
||||
m_current_free_size += GetUsedSize(p);
|
||||
}
|
||||
}
|
||||
|
||||
void *PeakCheckableMemoryResourceFromExpHeap::AllocateImpl(size_t size, size_t align) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
void *p = lmem::AllocateFromExpHeap(m_heap_handle, size, static_cast<s32>(align));
|
||||
this->OnAllocate(p, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
void PeakCheckableMemoryResourceFromExpHeap::DeallocateImpl(void *p, size_t size, size_t align) {
|
||||
AMS_UNUSED(align);
|
||||
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
this->OnDeallocate(p, size);
|
||||
lmem::FreeToExpHeap(m_heap_handle, p);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
MemoryResourceFromStandardAllocator::MemoryResourceFromStandardAllocator(mem::StandardAllocator *allocator) : m_allocator(allocator), m_mutex() {
|
||||
m_current_free_size = m_allocator->GetTotalFreeSize();
|
||||
this->ClearPeak();
|
||||
}
|
||||
|
||||
void MemoryResourceFromStandardAllocator::ClearPeak() {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
m_peak_free_size = m_current_free_size;
|
||||
m_peak_allocated_size = 0;
|
||||
}
|
||||
|
||||
void *MemoryResourceFromStandardAllocator::AllocateImpl(size_t size, size_t align) {
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
void *p = m_allocator->Allocate(size, align);
|
||||
|
||||
if (p != nullptr) {
|
||||
m_current_free_size -= m_allocator->GetSizeOf(p);
|
||||
m_peak_free_size = std::min(m_peak_free_size, m_current_free_size);
|
||||
}
|
||||
|
||||
m_peak_allocated_size = std::max(m_peak_allocated_size, size);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void MemoryResourceFromStandardAllocator::DeallocateImpl(void *p, size_t size, size_t align) {
|
||||
AMS_UNUSED(size, align);
|
||||
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
m_current_free_size += m_allocator->GetSizeOf(p);
|
||||
m_allocator->Free(p);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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>
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr inline const u8 HeaderSign1KeyModulusDev[fssystem::NcaCryptoConfiguration::Header1SignatureKeyGenerationMax + 1][fssystem::NcaCryptoConfiguration::Rsa2048KeyModulusSize] = {
|
||||
{
|
||||
0xD8, 0xF1, 0x18, 0xEF, 0x32, 0x72, 0x4C, 0xA7, 0x47, 0x4C, 0xB9, 0xEA, 0xB3, 0x04, 0xA8, 0xA4,
|
||||
0xAC, 0x99, 0x08, 0x08, 0x04, 0xBF, 0x68, 0x57, 0xB8, 0x43, 0x94, 0x2B, 0xC7, 0xB9, 0x66, 0x49,
|
||||
0x85, 0xE5, 0x8A, 0x9B, 0xC1, 0x00, 0x9A, 0x6A, 0x8D, 0xD0, 0xEF, 0xCE, 0xFF, 0x86, 0xC8, 0x5C,
|
||||
0x5D, 0xE9, 0x53, 0x7B, 0x19, 0x2A, 0xA8, 0xC0, 0x22, 0xD1, 0xF3, 0x22, 0x0A, 0x50, 0xF2, 0x2B,
|
||||
0x65, 0x05, 0x1B, 0x9E, 0xEC, 0x61, 0xB5, 0x63, 0xA3, 0x6F, 0x3B, 0xBA, 0x63, 0x3A, 0x53, 0xF4,
|
||||
0x49, 0x2F, 0xCF, 0x03, 0xCC, 0xD7, 0x50, 0x82, 0x1B, 0x29, 0x4F, 0x08, 0xDE, 0x1B, 0x6D, 0x47,
|
||||
0x4F, 0xA8, 0xB6, 0x6A, 0x26, 0xA0, 0x83, 0x3F, 0x1A, 0xAF, 0x83, 0x8F, 0x0E, 0x17, 0x3F, 0xFE,
|
||||
0x44, 0x1C, 0x56, 0x94, 0x2E, 0x49, 0x83, 0x83, 0x03, 0xE9, 0xB6, 0xAD, 0xD5, 0xDE, 0xE3, 0x2D,
|
||||
0xA1, 0xD9, 0x66, 0x20, 0x5D, 0x1F, 0x5E, 0x96, 0x5D, 0x5B, 0x55, 0x0D, 0xD4, 0xB4, 0x77, 0x6E,
|
||||
0xAE, 0x1B, 0x69, 0xF3, 0xA6, 0x61, 0x0E, 0x51, 0x62, 0x39, 0x28, 0x63, 0x75, 0x76, 0xBF, 0xB0,
|
||||
0xD2, 0x22, 0xEF, 0x98, 0x25, 0x02, 0x05, 0xC0, 0xD7, 0x6A, 0x06, 0x2C, 0xA5, 0xD8, 0x5A, 0x9D,
|
||||
0x7A, 0xA4, 0x21, 0x55, 0x9F, 0xF9, 0x3E, 0xBF, 0x16, 0xF6, 0x07, 0xC2, 0xB9, 0x6E, 0x87, 0x9E,
|
||||
0xB5, 0x1C, 0xBE, 0x97, 0xFA, 0x82, 0x7E, 0xED, 0x30, 0xD4, 0x66, 0x3F, 0xDE, 0xD8, 0x1B, 0x4B,
|
||||
0x15, 0xD9, 0xFB, 0x2F, 0x50, 0xF0, 0x9D, 0x1D, 0x52, 0x4C, 0x1C, 0x4D, 0x8D, 0xAE, 0x85, 0x1E,
|
||||
0xEA, 0x7F, 0x86, 0xF3, 0x0B, 0x7B, 0x87, 0x81, 0x98, 0x23, 0x80, 0x63, 0x4F, 0x2F, 0xB0, 0x62,
|
||||
0xCC, 0x6E, 0xD2, 0x46, 0x13, 0x65, 0x2B, 0xD6, 0x44, 0x33, 0x59, 0xB5, 0x8F, 0xB9, 0x4A, 0xA9
|
||||
},
|
||||
{
|
||||
0x9A, 0xBC, 0x88, 0xBD, 0x0A, 0xBE, 0xD7, 0x0C, 0x9B, 0x42, 0x75, 0x65, 0x38, 0x5E, 0xD1, 0x01,
|
||||
0xCD, 0x12, 0xAE, 0xEA, 0xE9, 0x4B, 0xDB, 0xB4, 0x5E, 0x36, 0x10, 0x96, 0xDA, 0x3D, 0x2E, 0x66,
|
||||
0xD3, 0x99, 0x13, 0x8A, 0xBE, 0x67, 0x41, 0xC8, 0x93, 0xD9, 0x3E, 0x42, 0xCE, 0x34, 0xCE, 0x96,
|
||||
0xFA, 0x0B, 0x23, 0xCC, 0x2C, 0xDF, 0x07, 0x3F, 0x3B, 0x24, 0x4B, 0x12, 0x67, 0x3A, 0x29, 0x36,
|
||||
0xA3, 0xAA, 0x06, 0xF0, 0x65, 0xA5, 0x85, 0xBA, 0xFD, 0x12, 0xEC, 0xF1, 0x60, 0x67, 0xF0, 0x8F,
|
||||
0xD3, 0x5B, 0x01, 0x1B, 0x1E, 0x84, 0xA3, 0x5C, 0x65, 0x36, 0xF9, 0x23, 0x7E, 0xF3, 0x26, 0x38,
|
||||
0x64, 0x98, 0xBA, 0xE4, 0x19, 0x91, 0x4C, 0x02, 0xCF, 0xC9, 0x6D, 0x86, 0xEC, 0x1D, 0x41, 0x69,
|
||||
0xDD, 0x56, 0xEA, 0x5C, 0xA3, 0x2A, 0x58, 0xB4, 0x39, 0xCC, 0x40, 0x31, 0xFD, 0xFB, 0x42, 0x74,
|
||||
0xF8, 0xEC, 0xEA, 0x00, 0xF0, 0xD9, 0x28, 0xEA, 0xFA, 0x2D, 0x00, 0xE1, 0x43, 0x53, 0xC6, 0x32,
|
||||
0xF4, 0xA2, 0x07, 0xD4, 0x5F, 0xD4, 0xCB, 0xAC, 0xCA, 0xFF, 0xDF, 0x84, 0xD2, 0x86, 0x14, 0x3C,
|
||||
0xDE, 0x22, 0x75, 0xA5, 0x73, 0xFF, 0x68, 0x07, 0x4A, 0xF9, 0x7C, 0x2C, 0xCC, 0xDE, 0x45, 0xB6,
|
||||
0x54, 0x82, 0x90, 0x36, 0x1F, 0x2C, 0x51, 0x96, 0xC5, 0x0A, 0x53, 0x5B, 0xF0, 0x8B, 0x4A, 0xAA,
|
||||
0x3B, 0x68, 0x97, 0x19, 0x17, 0x1F, 0x01, 0xB8, 0xED, 0xB9, 0x9A, 0x5E, 0x08, 0xC5, 0x20, 0x1E,
|
||||
0x6A, 0x09, 0xF0, 0xE9, 0x73, 0xA3, 0xBE, 0x10, 0x06, 0x02, 0xE9, 0xFB, 0x85, 0xFA, 0x5F, 0x01,
|
||||
0xAC, 0x60, 0xE0, 0xED, 0x7D, 0xB9, 0x49, 0xA8, 0x9E, 0x98, 0x7D, 0x91, 0x40, 0x05, 0xCF, 0xF9,
|
||||
0x1A, 0xFC, 0x40, 0x22, 0xA8, 0x96, 0x5B, 0xB0, 0xDC, 0x7A, 0xF5, 0xB7, 0xE9, 0x91, 0x4C, 0x49
|
||||
}
|
||||
};
|
||||
|
||||
constexpr inline const u8 HeaderSign1KeyModulusProd[fssystem::NcaCryptoConfiguration::Header1SignatureKeyGenerationMax + 1][fssystem::NcaCryptoConfiguration::Rsa2048KeyModulusSize] = {
|
||||
{
|
||||
0xBF, 0xBE, 0x40, 0x6C, 0xF4, 0xA7, 0x80, 0xE9, 0xF0, 0x7D, 0x0C, 0x99, 0x61, 0x1D, 0x77, 0x2F,
|
||||
0x96, 0xBC, 0x4B, 0x9E, 0x58, 0x38, 0x1B, 0x03, 0xAB, 0xB1, 0x75, 0x49, 0x9F, 0x2B, 0x4D, 0x58,
|
||||
0x34, 0xB0, 0x05, 0xA3, 0x75, 0x22, 0xBE, 0x1A, 0x3F, 0x03, 0x73, 0xAC, 0x70, 0x68, 0xD1, 0x16,
|
||||
0xB9, 0x04, 0x46, 0x5E, 0xB7, 0x07, 0x91, 0x2F, 0x07, 0x8B, 0x26, 0xDE, 0xF6, 0x00, 0x07, 0xB2,
|
||||
0xB4, 0x51, 0xF8, 0x0D, 0x0A, 0x5E, 0x58, 0xAD, 0xEB, 0xBC, 0x9A, 0xD6, 0x49, 0xB9, 0x64, 0xEF,
|
||||
0xA7, 0x82, 0xB5, 0xCF, 0x6D, 0x70, 0x13, 0xB0, 0x0F, 0x85, 0xF6, 0xA9, 0x08, 0xAA, 0x4D, 0x67,
|
||||
0x66, 0x87, 0xFA, 0x89, 0xFF, 0x75, 0x90, 0x18, 0x1E, 0x6B, 0x3D, 0xE9, 0x8A, 0x68, 0xC9, 0x26,
|
||||
0x04, 0xD9, 0x80, 0xCE, 0x3F, 0x5E, 0x92, 0xCE, 0x01, 0xFF, 0x06, 0x3B, 0xF2, 0xC1, 0xA9, 0x0C,
|
||||
0xCE, 0x02, 0x6F, 0x16, 0xBC, 0x92, 0x42, 0x0A, 0x41, 0x64, 0xCD, 0x52, 0xB6, 0x34, 0x4D, 0xAE,
|
||||
0xC0, 0x2E, 0xDE, 0xA4, 0xDF, 0x27, 0x68, 0x3C, 0xC1, 0xA0, 0x60, 0xAD, 0x43, 0xF3, 0xFC, 0x86,
|
||||
0xC1, 0x3E, 0x6C, 0x46, 0xF7, 0x7C, 0x29, 0x9F, 0xFA, 0xFD, 0xF0, 0xE3, 0xCE, 0x64, 0xE7, 0x35,
|
||||
0xF2, 0xF6, 0x56, 0x56, 0x6F, 0x6D, 0xF1, 0xE2, 0x42, 0xB0, 0x83, 0x40, 0xA5, 0xC3, 0x20, 0x2B,
|
||||
0xCC, 0x9A, 0xAE, 0xCA, 0xED, 0x4D, 0x70, 0x30, 0xA8, 0x70, 0x1C, 0x70, 0xFD, 0x13, 0x63, 0x29,
|
||||
0x02, 0x79, 0xEA, 0xD2, 0xA7, 0xAF, 0x35, 0x28, 0x32, 0x1C, 0x7B, 0xE6, 0x2F, 0x1A, 0xAA, 0x40,
|
||||
0x7E, 0x32, 0x8C, 0x27, 0x42, 0xFE, 0x82, 0x78, 0xEC, 0x0D, 0xEB, 0xE6, 0x83, 0x4B, 0x6D, 0x81,
|
||||
0x04, 0x40, 0x1A, 0x9E, 0x9A, 0x67, 0xF6, 0x72, 0x29, 0xFA, 0x04, 0xF0, 0x9D, 0xE4, 0xF4, 0x03
|
||||
},
|
||||
{
|
||||
0xAD, 0xE3, 0xE1, 0xFA, 0x04, 0x35, 0xE5, 0xB6, 0xDD, 0x49, 0xEA, 0x89, 0x29, 0xB1, 0xFF, 0xB6,
|
||||
0x43, 0xDF, 0xCA, 0x96, 0xA0, 0x4A, 0x13, 0xDF, 0x43, 0xD9, 0x94, 0x97, 0x96, 0x43, 0x65, 0x48,
|
||||
0x70, 0x58, 0x33, 0xA2, 0x7D, 0x35, 0x7B, 0x96, 0x74, 0x5E, 0x0B, 0x5C, 0x32, 0x18, 0x14, 0x24,
|
||||
0xC2, 0x58, 0xB3, 0x6C, 0x22, 0x7A, 0xA1, 0xB7, 0xCB, 0x90, 0xA7, 0xA3, 0xF9, 0x7D, 0x45, 0x16,
|
||||
0xA5, 0xC8, 0xED, 0x8F, 0xAD, 0x39, 0x5E, 0x9E, 0x4B, 0x51, 0x68, 0x7D, 0xF8, 0x0C, 0x35, 0xC6,
|
||||
0x3F, 0x91, 0xAE, 0x44, 0xA5, 0x92, 0x30, 0x0D, 0x46, 0xF8, 0x40, 0xFF, 0xD0, 0xFF, 0x06, 0xD2,
|
||||
0x1C, 0x7F, 0x96, 0x18, 0xDC, 0xB7, 0x1D, 0x66, 0x3E, 0xD1, 0x73, 0xBC, 0x15, 0x8A, 0x2F, 0x94,
|
||||
0xF3, 0x00, 0xC1, 0x83, 0xF1, 0xCD, 0xD7, 0x81, 0x88, 0xAB, 0xDF, 0x8C, 0xEF, 0x97, 0xDD, 0x1B,
|
||||
0x17, 0x5F, 0x58, 0xF6, 0x9A, 0xE9, 0xE8, 0xC2, 0x2F, 0x38, 0x15, 0xF5, 0x21, 0x07, 0xF8, 0x37,
|
||||
0x90, 0x5D, 0x2E, 0x02, 0x40, 0x24, 0x15, 0x0D, 0x25, 0xB7, 0x26, 0x5D, 0x09, 0xCC, 0x4C, 0xF4,
|
||||
0xF2, 0x1B, 0x94, 0x70, 0x5A, 0x9E, 0xEE, 0xED, 0x77, 0x77, 0xD4, 0x51, 0x99, 0xF5, 0xDC, 0x76,
|
||||
0x1E, 0xE3, 0x6C, 0x8C, 0xD1, 0x12, 0xD4, 0x57, 0xD1, 0xB6, 0x83, 0xE4, 0xE4, 0xFE, 0xDA, 0xE9,
|
||||
0xB4, 0x3B, 0x33, 0xE5, 0x37, 0x8A, 0xDF, 0xB5, 0x7F, 0x89, 0xF1, 0x9B, 0x9E, 0xB0, 0x15, 0xB2,
|
||||
0x3A, 0xFE, 0xEA, 0x61, 0x84, 0x5B, 0x7D, 0x4B, 0x23, 0x12, 0x0B, 0x83, 0x12, 0xF2, 0x22, 0x6B,
|
||||
0xB9, 0x22, 0x96, 0x4B, 0x26, 0x0B, 0x63, 0x5E, 0x96, 0x57, 0x52, 0xA3, 0x67, 0x64, 0x22, 0xCA,
|
||||
0xD0, 0x56, 0x3E, 0x74, 0xB5, 0x98, 0x1F, 0x0D, 0xF8, 0xB3, 0x34, 0xE6, 0x98, 0x68, 0x5A, 0xAD
|
||||
}
|
||||
};
|
||||
|
||||
constexpr inline const ::ams::fssystem::NcaCryptoConfiguration DefaultNcaCryptoConfigurationDev = {
|
||||
/* Header1 Signature Key Moduli */
|
||||
{ HeaderSign1KeyModulusDev[0], HeaderSign1KeyModulusDev[1] },
|
||||
|
||||
/* Header 1 Signature Key Public Exponent */
|
||||
{ 0x01, 0x00, 0x01 },
|
||||
|
||||
/* Key Area Encryption Key Sources */
|
||||
{
|
||||
/* Application */
|
||||
{ 0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D },
|
||||
|
||||
/* Ocean */
|
||||
{ 0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82 },
|
||||
|
||||
/* System */
|
||||
{ 0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A },
|
||||
},
|
||||
|
||||
/* Header Encryption Key Source */
|
||||
{ 0x1F, 0x12, 0x91, 0x3A, 0x4A, 0xCB, 0xF0, 0x0D, 0x4C, 0xDE, 0x3A, 0xF6, 0xD5, 0x23, 0x88, 0x2A },
|
||||
|
||||
/* Encrypted Header Encryption Key */
|
||||
{
|
||||
{ 0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0 },
|
||||
{ 0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2 }
|
||||
},
|
||||
|
||||
/* Key Generation Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Xts Eternal Function */
|
||||
nullptr,
|
||||
|
||||
/* Encrypt Aes Xts Eternal Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Ctr Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Ctr External Function */
|
||||
nullptr,
|
||||
|
||||
/* Verify Sign1 Function */
|
||||
nullptr,
|
||||
|
||||
/* Plaintext Header Available */
|
||||
false,
|
||||
|
||||
/* Software Key Available */
|
||||
true,
|
||||
};
|
||||
|
||||
constexpr inline const ::ams::fssystem::NcaCryptoConfiguration DefaultNcaCryptoConfigurationProd = {
|
||||
/* Header1 Signature Key Moduli */
|
||||
{ HeaderSign1KeyModulusProd[0], HeaderSign1KeyModulusProd[1] },
|
||||
|
||||
/* Header 1 Signature Key Public Exponent */
|
||||
{ 0x01, 0x00, 0x01 },
|
||||
|
||||
/* Key Area Encryption Key Sources */
|
||||
{
|
||||
/* Application */
|
||||
{ 0x7F, 0x59, 0x97, 0x1E, 0x62, 0x9F, 0x36, 0xA1, 0x30, 0x98, 0x06, 0x6F, 0x21, 0x44, 0xC3, 0x0D },
|
||||
|
||||
/* Ocean */
|
||||
{ 0x32, 0x7D, 0x36, 0x08, 0x5A, 0xD1, 0x75, 0x8D, 0xAB, 0x4E, 0x6F, 0xBA, 0xA5, 0x55, 0xD8, 0x82 },
|
||||
|
||||
/* System */
|
||||
{ 0x87, 0x45, 0xF1, 0xBB, 0xA6, 0xBE, 0x79, 0x64, 0x7D, 0x04, 0x8B, 0xA6, 0x7B, 0x5F, 0xDA, 0x4A },
|
||||
},
|
||||
|
||||
/* Header Encryption Key Source */
|
||||
{ 0x1F, 0x12, 0x91, 0x3A, 0x4A, 0xCB, 0xF0, 0x0D, 0x4C, 0xDE, 0x3A, 0xF6, 0xD5, 0x23, 0x88, 0x2A },
|
||||
|
||||
/* Encrypted Header Encryption Key */
|
||||
{
|
||||
{ 0x5A, 0x3E, 0xD8, 0x4F, 0xDE, 0xC0, 0xD8, 0x26, 0x31, 0xF7, 0xE2, 0x5D, 0x19, 0x7B, 0xF5, 0xD0 },
|
||||
{ 0x1C, 0x9B, 0x7B, 0xFA, 0xF6, 0x28, 0x18, 0x3D, 0x71, 0xF6, 0x4D, 0x73, 0xF1, 0x50, 0xB9, 0xD2 }
|
||||
},
|
||||
|
||||
/* Key Generation Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Xts Eternal Function */
|
||||
nullptr,
|
||||
|
||||
/* Encrypt Aes Xts Eternal Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Ctr Function */
|
||||
nullptr,
|
||||
|
||||
/* Decrypt Aes Ctr External Function */
|
||||
nullptr,
|
||||
|
||||
/* Verify Sign1 Function */
|
||||
nullptr,
|
||||
|
||||
/* Plaintext Header Available */
|
||||
false,
|
||||
|
||||
/* Software Key Available */
|
||||
true,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
const ::ams::fssystem::NcaCryptoConfiguration *GetDefaultNcaCryptoConfiguration(bool prod) {
|
||||
return prod ? std::addressof(DefaultNcaCryptoConfigurationProd) : std::addressof(DefaultNcaCryptoConfigurationDev);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "impl/fssrv_program_info.hpp"
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
namespace {
|
||||
|
||||
constinit ProgramRegistryServiceImpl *g_impl = nullptr;
|
||||
|
||||
}
|
||||
|
||||
ProgramRegistryImpl::ProgramRegistryImpl() : m_process_id(os::InvalidProcessId.value) {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
ProgramRegistryImpl::~ProgramRegistryImpl() {
|
||||
/* ... */
|
||||
}
|
||||
|
||||
void ProgramRegistryImpl::Initialize(ProgramRegistryServiceImpl *service) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(service != nullptr);
|
||||
AMS_ASSERT(g_impl == nullptr);
|
||||
|
||||
/* Set the global service. */
|
||||
g_impl = service;
|
||||
}
|
||||
|
||||
Result ProgramRegistryImpl::RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const ams::sf::InBuffer &data, s64 data_size, const ams::sf::InBuffer &desc, s64 desc_size) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(g_impl != nullptr);
|
||||
|
||||
/* Check that we're allowed to register. */
|
||||
R_UNLESS(fssrv::impl::IsInitialProgram(m_process_id), fs::ResultPermissionDenied());
|
||||
|
||||
/* Check buffer sizes. */
|
||||
R_UNLESS(data.GetSize() >= static_cast<size_t>(data_size), fs::ResultInvalidSize());
|
||||
R_UNLESS(desc.GetSize() >= static_cast<size_t>(desc_size), fs::ResultInvalidSize());
|
||||
|
||||
/* Register the program. */
|
||||
R_RETURN(g_impl->RegisterProgramInfo(process_id, program_id, storage_id, data.GetPointer(), data_size, desc.GetPointer(), desc_size));
|
||||
}
|
||||
|
||||
Result ProgramRegistryImpl::UnregisterProgram(u64 process_id) {
|
||||
/* Check pre-conditions. */
|
||||
AMS_ASSERT(g_impl != nullptr);
|
||||
|
||||
/* Check that we're allowed to register. */
|
||||
R_UNLESS(fssrv::impl::IsInitialProgram(m_process_id), fs::ResultPermissionDenied());
|
||||
|
||||
/* Unregister the program. */
|
||||
R_RETURN(g_impl->UnregisterProgramInfo(process_id));
|
||||
}
|
||||
|
||||
Result ProgramRegistryImpl::SetCurrentProcess(const ams::sf::ClientProcessId &client_pid) {
|
||||
/* Set our process id. */
|
||||
m_process_id = client_pid.GetValue().value;
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ProgramRegistryImpl::SetEnabledProgramVerification(bool en) {
|
||||
/* TODO: How to deal with this backwards compat? */
|
||||
AMS_ABORT("TODO: SetEnabledProgramVerification");
|
||||
AMS_UNUSED(en);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "impl/fssrv_program_info.hpp"
|
||||
#include "impl/fssrv_program_registry_manager.hpp"
|
||||
|
||||
namespace ams::fssrv {
|
||||
|
||||
Result ProgramRegistryServiceImpl::RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) {
|
||||
R_RETURN(m_registry_manager->RegisterProgram(process_id, program_id, storage_id, data, data_size, desc, desc_size));
|
||||
}
|
||||
|
||||
Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) {
|
||||
R_RETURN(m_registry_manager->UnregisterProgram(process_id));
|
||||
}
|
||||
|
||||
Result ProgramRegistryServiceImpl::ResetProgramIndexMapInfo(const fs::ProgramIndexMapInfo *infos, int count) {
|
||||
R_RETURN(m_index_map_info_manager->Reset(infos, count));
|
||||
}
|
||||
|
||||
Result ProgramRegistryServiceImpl::GetProgramInfo(std::shared_ptr<impl::ProgramInfo> *out, u64 process_id) {
|
||||
R_RETURN(m_registry_manager->GetProgramInfo(out, process_id));
|
||||
}
|
||||
|
||||
Result ProgramRegistryServiceImpl::GetProgramInfoByProgramId(std::shared_ptr<impl::ProgramInfo> *out, u64 program_id) {
|
||||
R_RETURN(m_registry_manager->GetProgramInfoByProgramId(out, program_id));
|
||||
}
|
||||
|
||||
size_t ProgramRegistryServiceImpl::GetProgramIndexMapInfoCount() {
|
||||
return m_index_map_info_manager->GetProgramCount();
|
||||
}
|
||||
|
||||
util::optional<fs::ProgramIndexMapInfo> ProgramRegistryServiceImpl::GetProgramIndexMapInfo(const ncm::ProgramId &program_id) {
|
||||
return m_index_map_info_manager->Get(program_id);
|
||||
}
|
||||
|
||||
ncm::ProgramId ProgramRegistryServiceImpl::GetProgramIdByIndex(const ncm::ProgramId &program_id, u8 index) {
|
||||
return m_index_map_info_manager->GetProgramId(program_id, index);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
template<typename F>
|
||||
ALWAYS_INLINE Result RetryFinitelyForDataCorrupted(F f) {
|
||||
/* All official uses of this retry once, for two tries total. */
|
||||
constexpr auto MaxTryCount = 2;
|
||||
|
||||
/* Perform the operation, retrying on fs::ResultDataCorrupted. */
|
||||
auto tries = 0;
|
||||
while (true) {
|
||||
/* Try to perform the operation. */
|
||||
const auto rc = f();
|
||||
|
||||
/* If we should, retry. */
|
||||
if (fs::ResultDataCorrupted::Includes(rc)) {
|
||||
if ((++tries) < MaxTryCount) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure the current attempt succeeded. */
|
||||
R_TRY(rc);
|
||||
|
||||
/* Return success. */
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 <stratosphere/fssrv/fssrv_interface_adapters.hpp>
|
||||
#include "fssrv_retry_utility.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
Result StorageInterfaceAdapter::Read(s64 offset, const ams::sf::OutNonSecureBuffer &buffer, s64 size) {
|
||||
/* Check pre-conditions. */
|
||||
R_UNLESS(0 <= offset, fs::ResultInvalidOffset());
|
||||
R_UNLESS(0 <= size, fs::ResultInvalidSize());
|
||||
R_UNLESS(size <= static_cast<s64>(buffer.GetSize()), fs::ResultInvalidSize());
|
||||
|
||||
R_RETURN(RetryFinitelyForDataCorrupted([&] () ALWAYS_INLINE_LAMBDA {
|
||||
R_RETURN(m_base_storage->Read(offset, buffer.GetPointer(), size));
|
||||
}));
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::Write(s64 offset, const ams::sf::InNonSecureBuffer &buffer, s64 size) {
|
||||
/* Check pre-conditions. */
|
||||
R_UNLESS(0 <= offset, fs::ResultInvalidOffset());
|
||||
R_UNLESS(0 <= size, fs::ResultInvalidSize());
|
||||
R_UNLESS(size <= static_cast<s64>(buffer.GetSize()), fs::ResultInvalidSize());
|
||||
|
||||
/* Temporarily increase our thread's priority. */
|
||||
fssystem::ScopedThreadPriorityChangerByAccessPriority cp(fssystem::ScopedThreadPriorityChangerByAccessPriority::AccessMode::Write);
|
||||
|
||||
R_RETURN(m_base_storage->Write(offset, buffer.GetPointer(), size));
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::Flush() {
|
||||
R_RETURN(m_base_storage->Flush());
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::SetSize(s64 size) {
|
||||
R_UNLESS(size >= 0, fs::ResultInvalidSize());
|
||||
R_RETURN(m_base_storage->SetSize(size));
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::GetSize(ams::sf::Out<s64> out) {
|
||||
R_RETURN(m_base_storage->GetSize(out.GetPointer()));
|
||||
}
|
||||
|
||||
Result StorageInterfaceAdapter::OperateRange(ams::sf::Out<fs::StorageQueryRangeInfo> out, s32 op_id, s64 offset, s64 size) {
|
||||
/* N includes this redundant check, so we will too. */
|
||||
R_UNLESS(out.GetPointer() != nullptr, fs::ResultNullptrArgument());
|
||||
|
||||
/* Clear the range info. */
|
||||
out->Clear();
|
||||
|
||||
if (op_id == static_cast<s32>(fs::OperationId::QueryRange)) {
|
||||
fs::FileQueryRangeInfo info;
|
||||
R_TRY(m_base_storage->OperateRange(std::addressof(info), sizeof(info), fs::OperationId::QueryRange, offset, size, nullptr, 0));
|
||||
out->Merge(info);
|
||||
} else if (op_id == static_cast<s32>(fs::OperationId::Invalidate)) {
|
||||
R_TRY(m_base_storage->OperateRange(nullptr, 0, fs::OperationId::Invalidate, offset, size, nullptr, 0));
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
class AllocatorForServiceFramework {
|
||||
public:
|
||||
using Policy = ams::sf::StatelessAllocationPolicy<AllocatorForServiceFramework>;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return fs::impl::Allocate(size);
|
||||
}
|
||||
|
||||
void Deallocate(void *ptr, size_t size) {
|
||||
return fs::impl::Deallocate(ptr, size);
|
||||
}
|
||||
};
|
||||
|
||||
using FileSystemObjectFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "fssrv_allocator_for_service_framework.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
namespace {
|
||||
|
||||
using FileSystemProxyServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
|
||||
using ProgramRegistryServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
|
||||
using FileSystemProxyForLoaderServiceFactory = ams::sf::ObjectFactory<AllocatorForServiceFramework::Policy>;
|
||||
|
||||
}
|
||||
|
||||
ams::sf::EmplacedRef<fssrv::sf::IFileSystemProxy, fssrv::FileSystemProxyImpl> GetFileSystemProxyServiceObject() {
|
||||
return FileSystemProxyServiceFactory::CreateSharedEmplaced<fssrv::sf::IFileSystemProxy, fssrv::FileSystemProxyImpl>();
|
||||
}
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IProgramRegistry> GetProgramRegistryServiceObject() {
|
||||
return ProgramRegistryServiceFactory::CreateSharedEmplaced<fssrv::sf::IProgramRegistry, fssrv::ProgramRegistryImpl>();
|
||||
}
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IProgramRegistry> GetInvalidProgramRegistryServiceObject() {
|
||||
return ProgramRegistryServiceFactory::CreateSharedEmplaced<fssrv::sf::IProgramRegistry, fssrv::InvalidProgramRegistryImpl>();
|
||||
}
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IFileSystemProxyForLoader> GetFileSystemProxyForLoaderServiceObject() {
|
||||
return FileSystemProxyForLoaderServiceFactory ::CreateSharedEmplaced<fssrv::sf::IFileSystemProxyForLoader, fssrv::FileSystemProxyImpl>();
|
||||
}
|
||||
|
||||
ams::sf::SharedPointer<fssrv::sf::IFileSystemProxyForLoader> GetInvalidFileSystemProxyForLoaderServiceObject() {
|
||||
return FileSystemProxyForLoaderServiceFactory ::CreateSharedEmplaced<fssrv::sf::IFileSystemProxyForLoader, fssrv::InvalidFileSystemProxyImplForLoader>();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "fssrv_program_info.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
namespace {
|
||||
|
||||
alignas(0x10) constinit std::byte g_static_buffer_for_program_info_for_initial_process[0x80] = {};
|
||||
|
||||
template<typename T>
|
||||
class StaticAllocatorForProgramInfoForInitialProcess : public std::allocator<T> {
|
||||
public:
|
||||
StaticAllocatorForProgramInfoForInitialProcess() { /* ... */ }
|
||||
|
||||
template<typename U>
|
||||
StaticAllocatorForProgramInfoForInitialProcess(const StaticAllocatorForProgramInfoForInitialProcess<U> &) { /* ... */ }
|
||||
|
||||
template<typename U>
|
||||
struct rebind {
|
||||
using other = StaticAllocatorForProgramInfoForInitialProcess<U>;
|
||||
};
|
||||
|
||||
[[nodiscard]] T *allocate(::std::size_t n) {
|
||||
AMS_ABORT_UNLESS(sizeof(T) * n <= sizeof(g_static_buffer_for_program_info_for_initial_process));
|
||||
return reinterpret_cast<T *>(std::addressof(g_static_buffer_for_program_info_for_initial_process));
|
||||
}
|
||||
|
||||
void deallocate(T *p, ::std::size_t n) {
|
||||
AMS_UNUSED(p, n);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr const u32 FileAccessControlForInitialProgram[0x1C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x0000001C, 0x00000000, 0x0000001C, 0x00000000};
|
||||
constexpr const u32 FileAccessControlDescForInitialProgram[0x2C / sizeof(u32)] = {0x00000001, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF};
|
||||
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
|
||||
constinit os::SdkMutex g_mutex;
|
||||
constinit bool g_initialized = false;
|
||||
|
||||
constinit u64 g_initial_process_id_min = 0;
|
||||
constinit u64 g_initial_process_id_max = 0;
|
||||
|
||||
constinit u64 g_current_process_id = 0;
|
||||
|
||||
ALWAYS_INLINE void InitializeInitialAndCurrentProcessId() {
|
||||
if (AMS_UNLIKELY(!g_initialized)) {
|
||||
std::scoped_lock lk(g_mutex);
|
||||
if (AMS_LIKELY(!g_initialized)) {
|
||||
/* Get initial process id range. */
|
||||
R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_min), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Minimum));
|
||||
R_ABORT_UNLESS(svc::GetSystemInfo(std::addressof(g_initial_process_id_max), svc::SystemInfoType_InitialProcessIdRange, svc::InvalidHandle, svc::InitialProcessIdRangeInfo_Maximum));
|
||||
|
||||
AMS_ABORT_UNLESS(0 < g_initial_process_id_min);
|
||||
AMS_ABORT_UNLESS(g_initial_process_id_min <= g_initial_process_id_max);
|
||||
|
||||
/* Get current procss id. */
|
||||
R_ABORT_UNLESS(svc::GetProcessId(std::addressof(g_current_process_id), svc::PseudoHandle::CurrentProcess));
|
||||
|
||||
/* Set initialized. */
|
||||
g_initialized = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
std::shared_ptr<ProgramInfo> ProgramInfo::GetProgramInfoForInitialProcess() {
|
||||
class ProgramInfoHelper : public ProgramInfo {
|
||||
public:
|
||||
ProgramInfoHelper(const void *data, s64 data_size, const void *desc, s64 desc_size) : ProgramInfo(data, data_size, desc, desc_size) { /* ... */ }
|
||||
};
|
||||
|
||||
AMS_FUNCTION_LOCAL_STATIC(std::shared_ptr<ProgramInfo>, s_initial_program_info, std::allocate_shared<ProgramInfoHelper>(StaticAllocatorForProgramInfoForInitialProcess<char>{}, FileAccessControlForInitialProgram, sizeof(FileAccessControlForInitialProgram), FileAccessControlDescForInitialProgram, sizeof(FileAccessControlDescForInitialProgram)));
|
||||
|
||||
return s_initial_program_info;
|
||||
}
|
||||
|
||||
bool IsInitialProgram(u64 process_id) {
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
/* Initialize/sanity check. */
|
||||
InitializeInitialAndCurrentProcessId();
|
||||
AMS_ABORT_UNLESS(g_initial_process_id_min > 0);
|
||||
|
||||
/* Check process id in range. */
|
||||
return g_initial_process_id_min <= process_id && process_id <= g_initial_process_id_max;
|
||||
#elif defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX) || defined(ATMOSPHERE_OS_MACOS)
|
||||
AMS_UNUSED(process_id);
|
||||
return true;
|
||||
#else
|
||||
#error "Unknown os for fssrv::impl::IsInitialProgram"
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IsCurrentProcess(u64 process_id) {
|
||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||
/* Initialize. */
|
||||
InitializeInitialAndCurrentProcessId();
|
||||
|
||||
return process_id == g_current_process_id;
|
||||
#elif defined(ATMOSPHERE_OS_WINDOWS) || defined(ATMOSPHERE_OS_LINUX) || defined(ATMOSPHERE_OS_MACOS)
|
||||
AMS_UNUSED(process_id);
|
||||
return true;
|
||||
#else
|
||||
#error "Unknown os for fssrv::impl::IsCurrentProcess"
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
class ProgramInfo : public ::ams::fs::impl::Newable {
|
||||
private:
|
||||
u64 m_process_id;
|
||||
ncm::ProgramId m_program_id;
|
||||
ncm::StorageId m_storage_id;
|
||||
/* TODO: AccessControl m_access_control; */
|
||||
public:
|
||||
ProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) : m_process_id(process_id) /* TODO: m_access_control */ {
|
||||
m_program_id.value = program_id;
|
||||
m_storage_id = static_cast<ncm::StorageId>(storage_id);
|
||||
|
||||
/* TODO */
|
||||
AMS_UNUSED(data, data_size, desc, desc_size);
|
||||
}
|
||||
|
||||
bool Contains(u64 process_id) const { return m_process_id == process_id; }
|
||||
u64 GetProcessId() const { return m_process_id; }
|
||||
ncm::ProgramId GetProgramId() const { return m_program_id; }
|
||||
u64 GetProgramIdValue() const { return m_program_id.value; }
|
||||
ncm::StorageId GetStorageId() const { return m_storage_id; }
|
||||
public:
|
||||
static std::shared_ptr<ProgramInfo> GetProgramInfoForInitialProcess();
|
||||
private:
|
||||
ProgramInfo(const void *data, s64 data_size, const void *desc, s64 desc_size) : m_process_id(os::InvalidProcessId), m_program_id(ncm::InvalidProgramId), m_storage_id(static_cast<ncm::StorageId>(0)) /* TODO: m_access_control */ {
|
||||
/* TODO */
|
||||
AMS_UNUSED(data, data_size, desc, desc_size);
|
||||
}
|
||||
};
|
||||
|
||||
struct ProgramInfoNode : public util::IntrusiveListBaseNode<ProgramInfoNode>, public ::ams::fs::impl::Newable {
|
||||
std::shared_ptr<ProgramInfo> program_info;
|
||||
};
|
||||
|
||||
bool IsInitialProgram(u64 process_id);
|
||||
bool IsCurrentProcess(u64 process_id);
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "fssrv_program_registry_manager.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
Result ProgramRegistryManager::RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) {
|
||||
/* Allocate a new node. */
|
||||
std::unique_ptr<ProgramInfoNode> new_node(new ProgramInfoNode());
|
||||
R_UNLESS(new_node != nullptr, fs::ResultAllocationMemoryFailedInProgramRegistryManagerA());
|
||||
|
||||
/* Create a new program info. */
|
||||
{
|
||||
/* Allocate the new info. */
|
||||
auto new_info = fssystem::AllocateShared<ProgramInfo>(process_id, program_id, storage_id, data, data_size, desc, desc_size);
|
||||
R_UNLESS(new_info != nullptr, fs::ResultAllocationMemoryFailedInProgramRegistryManagerA());
|
||||
|
||||
/* Set the info in the node. */
|
||||
new_node->program_info = std::move(new_info);
|
||||
}
|
||||
|
||||
/* Acquire exclusive access to the registry. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Check that the process isn't already in the registry. */
|
||||
for (const auto &node : m_program_info_list) {
|
||||
R_UNLESS(!node.program_info->Contains(process_id), fs::ResultInvalidArgument());
|
||||
}
|
||||
|
||||
/* Add the node to the registry. */
|
||||
m_program_info_list.push_back(*new_node.release());
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ProgramRegistryManager::UnregisterProgram(u64 process_id) {
|
||||
/* Acquire exclusive access to the registry. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Try to find and remove the process's node. */
|
||||
for (auto &node : m_program_info_list) {
|
||||
if (node.program_info->Contains(process_id)) {
|
||||
m_program_info_list.erase(m_program_info_list.iterator_to(node));
|
||||
delete std::addressof(node);
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
/* We couldn't find/unregister the process's node. */
|
||||
R_THROW(fs::ResultInvalidArgument());
|
||||
}
|
||||
|
||||
Result ProgramRegistryManager::GetProgramInfo(std::shared_ptr<ProgramInfo> *out, u64 process_id) {
|
||||
/* Acquire exclusive access to the registry. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Check if we're getting permissions for an initial program. */
|
||||
if (IsInitialProgram(process_id)) {
|
||||
*out = ProgramInfo::GetProgramInfoForInitialProcess();
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
/* Find a matching node. */
|
||||
for (const auto &node : m_program_info_list) {
|
||||
if (node.program_info->Contains(process_id)) {
|
||||
*out = node.program_info;
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
/* We didn't find the program info. */
|
||||
R_THROW(fs::ResultProgramInfoNotFound());
|
||||
}
|
||||
|
||||
Result ProgramRegistryManager::GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo> *out, u64 program_id) {
|
||||
/* Acquire exclusive access to the registry. */
|
||||
std::scoped_lock lk(m_mutex);
|
||||
|
||||
/* Find a matching node. */
|
||||
for (const auto &node : m_program_info_list) {
|
||||
if (node.program_info->GetProgramIdValue() == program_id) {
|
||||
*out = node.program_info;
|
||||
R_SUCCEED();
|
||||
}
|
||||
}
|
||||
|
||||
/* We didn't find the program info. */
|
||||
R_THROW(fs::ResultProgramInfoNotFound());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
#include "fssrv_program_info.hpp"
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
class ProgramRegistryManager {
|
||||
NON_COPYABLE(ProgramRegistryManager);
|
||||
NON_MOVEABLE(ProgramRegistryManager);
|
||||
private:
|
||||
using ProgramInfoList = util::IntrusiveListBaseTraits<ProgramInfoNode>::ListType;
|
||||
private:
|
||||
ProgramInfoList m_program_info_list{};
|
||||
os::SdkMutex m_mutex{};
|
||||
public:
|
||||
constexpr ProgramRegistryManager() = default;
|
||||
|
||||
Result RegisterProgram(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size);
|
||||
Result UnregisterProgram(u64 process_id);
|
||||
|
||||
Result GetProgramInfo(std::shared_ptr<ProgramInfo> *out, u64 process_id);
|
||||
Result GetProgramInfoByProgramId(std::shared_ptr<ProgramInfo> *out, u64 program_id);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
AMS_FSSYSTEM_ENABLE_PIMPL(::ams::fssrv::impl::ProgramRegistryManager);
|
||||
@@ -1,202 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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 "fssrv_utility.hpp"
|
||||
|
||||
|
||||
#if defined(ATMOSPHERE_OS_WINDOWS)
|
||||
#include <stratosphere/windows.hpp>
|
||||
#elif defined(ATMOSPHERE_OS_LINUX)
|
||||
#include <unistd.h>
|
||||
#elif defined(ATMOSPHERE_OS_MACOS)
|
||||
#include <unistd.h>
|
||||
#include <mach-o/dyld.h>
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
namespace ams::fssystem {
|
||||
|
||||
class PathOnExecutionDirectory {
|
||||
private:
|
||||
char m_path[fs::EntryNameLengthMax + 1];
|
||||
public:
|
||||
PathOnExecutionDirectory() {
|
||||
#if defined(ATMOSPHERE_OS_WINDOWS)
|
||||
{
|
||||
/* Get the module file name. */
|
||||
wchar_t module_file_name[fs::EntryNameLengthMax + 1];
|
||||
if (::GetModuleFileNameW(0, module_file_name, util::size(module_file_name)) == 0) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
|
||||
}
|
||||
|
||||
/* Split the path. */
|
||||
wchar_t drive_name[3];
|
||||
wchar_t dir_name[fs::EntryNameLengthMax + 1];
|
||||
::_wsplitpath_s(module_file_name, drive_name, util::size(drive_name), dir_name, util::size(dir_name), nullptr, 0, nullptr, 0);
|
||||
|
||||
/* Print the drive and directory. */
|
||||
wchar_t path[fs::EntryNameLengthMax + 1];
|
||||
::swprintf_s(path, util::size(path), L"%s%s", drive_name, dir_name);
|
||||
|
||||
/* Convert to utf-8. */
|
||||
const auto res = ::WideCharToMultiByte(CP_UTF8, 0, path, -1, m_path, util::size(m_path), nullptr, nullptr);
|
||||
if (res == 0) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_LINUX)
|
||||
{
|
||||
char full_path[PATH_MAX] = {};
|
||||
if (::readlink("/proc/self/exe", full_path, sizeof(full_path)) == -1) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
|
||||
}
|
||||
|
||||
const int len = std::strlen(full_path);
|
||||
if (len >= static_cast<int>(sizeof(m_path))) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
std::memcpy(m_path, full_path, len + 1);
|
||||
|
||||
for (int i = len - 1; i >= 0; --i) {
|
||||
if (m_path[i] == '/') {
|
||||
m_path[i + 1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_MACOS)
|
||||
{
|
||||
char full_path[MAXPATHLEN] = {};
|
||||
uint32_t size = sizeof(full_path);
|
||||
if (_NSGetExecutablePath(full_path, std::addressof(size)) != 0) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryA());
|
||||
}
|
||||
|
||||
const int len = std::strlen(full_path);
|
||||
if (len >= static_cast<int>(sizeof(m_path))) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
std::memcpy(m_path, full_path, len + 1);
|
||||
|
||||
for (int i = len - 1; i >= 0; --i) {
|
||||
if (m_path[i] == '/') {
|
||||
m_path[i + 1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
AMS_ABORT("TODO: Unknown OS for PathOnExecutionDirectory");
|
||||
#endif
|
||||
|
||||
const auto len = std::strlen(m_path);
|
||||
if (m_path[len - 1] != '/' && m_path[len - 1] != '\\') {
|
||||
if (len + 1 >= sizeof(m_path)) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
m_path[len] = '/';
|
||||
m_path[len + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Get() const {
|
||||
return m_path;
|
||||
}
|
||||
};
|
||||
|
||||
class PathOnWorkingDirectory {
|
||||
private:
|
||||
char m_path[fs::EntryNameLengthMax + 1];
|
||||
public:
|
||||
PathOnWorkingDirectory() {
|
||||
#if defined(ATMOSPHERE_OS_WINDOWS)
|
||||
{
|
||||
/* Get the current directory. */
|
||||
wchar_t current_directory[fs::EntryNameLengthMax + 1];
|
||||
if (::GetCurrentDirectoryW(util::size(current_directory), current_directory) == 0) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
/* Convert to utf-8. */
|
||||
const auto res = ::WideCharToMultiByte(CP_UTF8, 0, current_directory, -1, m_path, util::size(m_path), nullptr, nullptr);
|
||||
if (res == 0) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_LINUX)
|
||||
{
|
||||
char full_path[PATH_MAX] = {};
|
||||
if (::getcwd(full_path, sizeof(full_path)) == nullptr) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
const int len = std::strlen(full_path);
|
||||
if (len >= static_cast<int>(sizeof(m_path))) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
std::memcpy(m_path, full_path, len + 1);
|
||||
}
|
||||
#elif defined(ATMOSPHERE_OS_MACOS)
|
||||
{
|
||||
char full_path[MAXPATHLEN] = {};
|
||||
if (::getcwd(full_path, sizeof(full_path)) == nullptr) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
const int len = std::strlen(full_path);
|
||||
if (len >= static_cast<int>(sizeof(m_path))) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
|
||||
std::memcpy(m_path, full_path, len + 1);
|
||||
}
|
||||
#else
|
||||
AMS_ABORT("TODO: Unknown OS for PathOnWorkingDirectory");
|
||||
#endif
|
||||
|
||||
const auto len = std::strlen(m_path);
|
||||
if (m_path[len - 1] != '/' && m_path[len - 1] != '\\') {
|
||||
if (len + 1 >= sizeof(m_path)) {
|
||||
AMS_FS_R_ABORT_UNLESS(fs::ResultUnexpectedInPathOnExecutionDirectoryB());
|
||||
}
|
||||
m_path[len] = '/';
|
||||
m_path[len + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
const char *Get() const {
|
||||
return m_path;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
const char *GetExecutionDirectoryPath() {
|
||||
AMS_FUNCTION_LOCAL_STATIC(fssystem::PathOnExecutionDirectory, s_path_on_execution_directory);
|
||||
return s_path_on_execution_directory.Get();
|
||||
}
|
||||
|
||||
const char *GetWorkingDirectoryPath() {
|
||||
AMS_FUNCTION_LOCAL_STATIC(fssystem::PathOnWorkingDirectory, s_path_on_working_directory);
|
||||
return s_path_on_working_directory.Get();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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.hpp>
|
||||
|
||||
namespace ams::fssrv::impl {
|
||||
|
||||
const char *GetExecutionDirectoryPath();
|
||||
const char *GetWorkingDirectoryPath();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user