mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <stratosphere/fs/fs_common.hpp>
|
||||
#include <vapours.hpp>
|
||||
#include <stratosphere/ncm/ncm_ids.hpp>
|
||||
|
||||
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 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 "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) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(process_id, program_id, storage_id, data, data_size, desc, desc_size);
|
||||
return m_registry_manager->RegisterProgram(process_id, program_id, storage_id, data, data_size, desc, desc_size);
|
||||
}
|
||||
|
||||
Result ProgramRegistryServiceImpl::UnregisterProgramInfo(u64 process_id) {
|
||||
AMS_ABORT("TODO");
|
||||
AMS_UNUSED(process_id);
|
||||
return m_registry_manager->UnregisterProgram(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 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() {
|
||||
if (AMS_UNLIKELY(!g_initialized)) {
|
||||
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) {
|
||||
/* Initialize/sanity check. */
|
||||
InitializeInitialAndCurrentProcessId();
|
||||
|
|
|
@ -32,6 +32,19 @@ namespace ams::fssrv::impl {
|
|||
/* 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(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 {
|
||||
|
|
|
@ -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(AllocationFailureInFileSystemProxyCoreImplD, 3256);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInFileSystemProxyCoreImplE, 3257);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInProgramRegistryManagerA, 3258);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInPartitionFileSystemCreatorA, 3280);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInRomFileSystemCreatorA, 3281);
|
||||
R_DEFINE_ERROR_RESULT(AllocationFailureInStorageOnNcaCreatorA, 3288);
|
||||
|
@ -375,6 +376,7 @@ namespace ams::fs {
|
|||
R_DEFINE_ERROR_RESULT(UserNotExist, 6465);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(NotFound, 6600, 6699);
|
||||
R_DEFINE_ERROR_RESULT(ProgramInfoNotFound, 6605);
|
||||
|
||||
R_DEFINE_ERROR_RANGE(OutOfResource, 6700, 6799);
|
||||
R_DEFINE_ERROR_RESULT(BufferAllocationFailed, 6705);
|
||||
|
|
Loading…
Reference in a new issue