mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
fssrv: flesh out the program registry
This commit is contained in:
parent
e8d14eb77d
commit
28ea6555f8
7 changed files with 209 additions and 5 deletions
|
@ -14,7 +14,8 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <stratosphere/fs/fs_common.hpp>
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/ncm/ncm_ids.hpp>
|
||||||
|
|
||||||
namespace ams::fs {
|
namespace ams::fs {
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,16 @@ namespace ams::fssrv {
|
||||||
|
|
||||||
Result RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size);
|
Result RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size);
|
||||||
Result UnregisterProgramInfo(u64 process_id);
|
Result UnregisterProgramInfo(u64 process_id);
|
||||||
|
|
||||||
|
Result ResetProgramIndexMapInfo(const fs::ProgramIndexMapInfo *infos, int count);
|
||||||
|
|
||||||
|
Result GetProgramInfo(std::shared_ptr<impl::ProgramInfo> *out, u64 process_id);
|
||||||
|
Result GetProgramInfoByProgramId(std::shared_ptr<impl::ProgramInfo> *out, u64 program_id);
|
||||||
|
|
||||||
|
size_t GetProgramIndexMapInfoCount();
|
||||||
|
util::optional<fs::ProgramIndexMapInfo> GetProgramIndexMapInfo(const ncm::ProgramId &program_id);
|
||||||
|
|
||||||
|
ncm::ProgramId GetProgramIdByIndex(const ncm::ProgramId &program_id, u8 index);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,40 @@
|
||||||
*/
|
*/
|
||||||
#include <stratosphere.hpp>
|
#include <stratosphere.hpp>
|
||||||
#include "impl/fssrv_program_info.hpp"
|
#include "impl/fssrv_program_info.hpp"
|
||||||
|
#include "impl/fssrv_program_registry_manager.hpp"
|
||||||
|
|
||||||
namespace ams::fssrv {
|
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) {
|
Result ProgramRegistryServiceImpl::RegisterProgramInfo(u64 process_id, u64 program_id, u8 storage_id, const void *data, s64 data_size, const void *desc, s64 desc_size) {
|
||||||
AMS_ABORT("TODO");
|
return m_registry_manager->RegisterProgram(process_id, program_id, storage_id, data, data_size, desc, desc_size);
|
||||||
AMS_UNUSED(process_id, program_id, storage_id, data, data_size, desc, desc_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) {
|
Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) {
|
||||||
AMS_ABORT("TODO");
|
return m_registry_manager->UnregisterProgram(process_id);
|
||||||
AMS_UNUSED(process_id);
|
}
|
||||||
|
|
||||||
|
Result ProgramRegistryServiceImpl::ResetProgramIndexMapInfo(const fs::ProgramIndexMapInfo *infos, int count) {
|
||||||
|
return m_index_map_info_manager->Reset(infos, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProgramRegistryServiceImpl::GetProgramInfo(std::shared_ptr<impl::ProgramInfo> *out, u64 process_id) {
|
||||||
|
return m_registry_manager->GetProgramInfo(out, process_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProgramRegistryServiceImpl::GetProgramInfoByProgramId(std::shared_ptr<impl::ProgramInfo> *out, u64 program_id) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,34 @@ namespace ams::fssrv::impl {
|
||||||
|
|
||||||
constinit u64 g_current_process_id = 0;
|
constinit u64 g_current_process_id = 0;
|
||||||
|
|
||||||
|
constinit std::aligned_storage<0x80>::type g_static_buffer_for_program_info_for_initial_process;
|
||||||
|
|
||||||
|
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};
|
||||||
|
|
||||||
ALWAYS_INLINE void InitializeInitialAndCurrentProcessId() {
|
ALWAYS_INLINE void InitializeInitialAndCurrentProcessId() {
|
||||||
if (AMS_UNLIKELY(!g_initialized)) {
|
if (AMS_UNLIKELY(!g_initialized)) {
|
||||||
std::scoped_lock lk(g_mutex);
|
std::scoped_lock lk(g_mutex);
|
||||||
|
@ -50,6 +78,28 @@ namespace ams::fssrv::impl {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<ProgramInfo> ProgramInfo::GetProgramInfoForInitialProcess() {
|
||||||
|
static constinit os::SdkMutex s_mutex;
|
||||||
|
static constinit bool s_initialized = false;
|
||||||
|
static constinit std::shared_ptr<ProgramInfo> s_initial_program_info = nullptr;
|
||||||
|
|
||||||
|
/* Ensure we've initialized the program info. */
|
||||||
|
if (AMS_UNLIKELY(!s_initialized)) {
|
||||||
|
std::scoped_lock lk(s_mutex);
|
||||||
|
if (AMS_LIKELY(!s_initialized)) {
|
||||||
|
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) { /* ... */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
s_initial_program_info = std::allocate_shared<ProgramInfoHelper>(StaticAllocatorForProgramInfoForInitialProcess<char>{}, FileAccessControlForInitialProgram, sizeof(FileAccessControlForInitialProgram), FileAccessControlDescForInitialProgram, sizeof(FileAccessControlDescForInitialProgram));
|
||||||
|
s_initialized = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_initial_program_info;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsInitialProgram(u64 process_id) {
|
bool IsInitialProgram(u64 process_id) {
|
||||||
/* Initialize/sanity check. */
|
/* Initialize/sanity check. */
|
||||||
InitializeInitialAndCurrentProcessId();
|
InitializeInitialAndCurrentProcessId();
|
||||||
|
|
|
@ -32,6 +32,19 @@ namespace ams::fssrv::impl {
|
||||||
/* TODO */
|
/* TODO */
|
||||||
AMS_UNUSED(data, data_size, desc, desc_size);
|
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(0), m_program_id(0), 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 {
|
struct ProgramInfoNode : public util::IntrusiveListBaseNode<ProgramInfoNode>, public ::ams::fs::impl::Newable {
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/*
|
||||||
|
* 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::ResultAllocationFailureInProgramRegistryManagerA());
|
||||||
|
|
||||||
|
/* 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::ResultAllocationFailureInProgramRegistryManagerA());
|
||||||
|
|
||||||
|
/* 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());
|
||||||
|
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We couldn't find/unregister the process's node. */
|
||||||
|
return 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();
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find a matching node. */
|
||||||
|
for (const auto &node : m_program_info_list) {
|
||||||
|
if (node.program_info->Contains(process_id)) {
|
||||||
|
*out = node.program_info;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find the program info. */
|
||||||
|
return 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;
|
||||||
|
return ResultSuccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We didn't find the program info. */
|
||||||
|
return fs::ResultProgramInfoNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -82,6 +82,7 @@ namespace ams::fs {
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFsFileSystemC, 3249);
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplD, 3256);
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257);
|
||||||
|
R_DEFINE_ERROR_RESULT(AllocationFailureInProgramRegistryManagerA, 3258);
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
|
||||||
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
|
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
|
||||||
|
@ -375,6 +376,7 @@ namespace ams::fs {
|
||||||
R_DEFINE_ERROR_RESULT(UserNotExist, 6465);
|
R_DEFINE_ERROR_RESULT(UserNotExist, 6465);
|
||||||
|
|
||||||
R_DEFINE_ERROR_RANGE(NotFound, 6600, 6699);
|
R_DEFINE_ERROR_RANGE(NotFound, 6600, 6699);
|
||||||
|
R_DEFINE_ERROR_RESULT(ProgramInfoNotFound, 6605);
|
||||||
|
|
||||||
R_DEFINE_ERROR_RANGE(OutOfResource, 6700, 6799);
|
R_DEFINE_ERROR_RANGE(OutOfResource, 6700, 6799);
|
||||||
R_DEFINE_ERROR_RESULT(BufferAllocationFailed, 6705);
|
R_DEFINE_ERROR_RESULT(BufferAllocationFailed, 6705);
|
||||||
|
|
Loading…
Reference in a new issue