Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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;
}
};
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();
}
}
}

View File

@@ -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();
}
}

View File

@@ -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>;
}

View File

@@ -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>();
}
}

View File

@@ -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
}
}

View File

@@ -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);
}

View File

@@ -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());
}
}

View File

@@ -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);

View File

@@ -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();
}
}

View File

@@ -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();
}