From f5e98de1a39775b87b147b1b94446e193617b23f Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 9 Feb 2021 23:09:28 -0800 Subject: [PATCH] htc: add RpcTaskTable --- .../htc/server/rpc/htc_htcmisc_rpc_tasks.hpp | 10 +- .../source/htc/server/rpc/htc_rpc_client.cpp | 4 +- .../source/htc/server/rpc/htc_rpc_client.hpp | 9 +- .../htc/server/rpc/htc_rpc_task_table.hpp | 109 ++++++++++++++++++ .../source/htc/server/rpc/htc_rpc_tasks.hpp | 2 + 5 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 libraries/libstratosphere/source/htc/server/rpc/htc_rpc_task_table.hpp diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_tasks.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_tasks.hpp index d2015fb85..983b36b4c 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_tasks.hpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_htcmisc_rpc_tasks.hpp @@ -39,8 +39,8 @@ namespace ams::htc::server::rpc { }; enum class HtcmiscPacketType : s16 { - GetMaxProtocolVersion = 0, - SetProtocolVersion = 1, + GetMaxProtocolVersion = 0, + SetProtocolVersion = 1, GetEnvironmentVariable = 16, GetEnvironmentVariableLength = 17, SetTargetStatus = 18, @@ -75,6 +75,8 @@ namespace ams::htc::server::rpc { }; class GetEnvironmentVariableTask : public HtcmiscTask { + public: + static constexpr inline HtcmiscTaskType TaskType = HtcmiscTaskType::GetEnvironmentVariable; private: char m_name[0x800]; int m_name_size; @@ -96,6 +98,8 @@ namespace ams::htc::server::rpc { }; class GetEnvironmentVariableLengthTask : public HtcmiscTask { + public: + static constexpr inline HtcmiscTaskType TaskType = HtcmiscTaskType::GetEnvironmentVariableLength; private: char m_name[0x800]; int m_name_size; @@ -116,6 +120,8 @@ namespace ams::htc::server::rpc { }; class RunOnHostTask : public HtcmiscTask { + public: + static constexpr inline HtcmiscTaskType TaskType = HtcmiscTaskType::RunOnHost; private: char m_command[0x2000]; int m_command_size; diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp index 394252c8e..5b9f4beae 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.cpp @@ -36,12 +36,12 @@ namespace ams::htc::server::rpc { m_receive_thread_stack(g_receive_thread_stack), m_send_thread_stack(g_send_thread_stack), m_mutex(g_rpc_mutex), + m_task_table(), m_cancelled(false), m_thread_running(false) { /* Initialize all events. */ - /* TODO: MaxTaskCount? */ - for (size_t i = 0; i < util::size(m_5F8_events); ++i) { + for (size_t i = 0; i < MaxTaskCount; ++i) { os::InitializeEvent(std::addressof(m_5F8_events[i]), false, os::EventClearMode_AutoClear); os::InitializeEvent(std::addressof(m_1138_events[i]), false, os::EventClearMode_AutoClear); } diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp index 52811489f..d626b861f 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_client.hpp @@ -16,6 +16,7 @@ #pragma once #include #include "../driver/htc_i_driver.hpp" +#include "htc_rpc_task_table.hpp" namespace ams::htc::server::rpc { @@ -30,13 +31,13 @@ namespace ams::htc::server::rpc { os::ThreadType m_send_thread; os::SdkMutex &m_mutex; /* TODO: m_task_id_free_list */ - /* TODO: m_task_table */ - /* TODO: m_3C0[0x48] */ + RpcTaskTable m_task_table; + /* TODO: m_3C0[MaxTaskCount] */ /* TODO: m_rpc_task_queue */ bool m_cancelled; bool m_thread_running; - os::EventType m_5F8_events[0x48]; - os::EventType m_1138_events[0x48]; + os::EventType m_5F8_events[MaxTaskCount]; + os::EventType m_1138_events[MaxTaskCount]; public: RpcClient(driver::IDriver *driver, htclow::ChannelId channel); }; diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_task_table.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_task_table.hpp new file mode 100644 index 000000000..5a22e7cf9 --- /dev/null +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_task_table.hpp @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include "htc_rpc_tasks.hpp" +#include "htc_htcmisc_rpc_tasks.hpp" + +namespace ams::htc::server::rpc { + + /* For convenience. */ + template + concept IsTypeCheckableTask = std::derived_from && requires (T &t) { + { t.GetTaskType() } -> std::convertible_to; + }; + + static_assert(!IsTypeCheckableTask); + static_assert(IsTypeCheckableTask); + + class RpcTaskTable { + private: + /* TODO: How is this variable derived...? */ + /* Nintendo has a value of 0xE1D8, which is deeply magic. */ + static constexpr size_t MaxTaskSize = 0xA000; + using TaskStorage = typename std::aligned_storage::type; + private: + bool m_valid[MaxTaskCount]; + TaskStorage m_storages[MaxTaskCount]; + private: + template + ALWAYS_INLINE T *GetPointer(u32 index) { + static_assert(alignof(T) <= alignof(TaskStorage)); + static_assert(sizeof(T) <= sizeof(TaskStorage)); + return reinterpret_cast(std::addressof(m_storages[index])); + } + + ALWAYS_INLINE bool IsValid(u32 index) { + return index < MaxTaskCount && m_valid[index]; + } + public: + RpcTaskTable() : m_valid() { /* ... */ } + + template requires std::derived_from + T *New(u32 index) { + /* Sanity check input. */ + AMS_ASSERT(!this->IsValid(index)); + + /* Set valid. */ + m_valid[index] = true; + + /* Allocate the task. */ + T *task = this->GetPointer(index); + + /* Create the task. */ + std::construct_at(task); + + /* Return the task. */ + return task; + } + + template requires std::derived_from + T *Get(u32 index) { + /* Check that the task is valid. */ + if (!this->IsValid(index)) { + return false; + } + + /* Get the task pointer. */ + T *task = this->GetPointer(index); + + /* Type check the task. */ + if constexpr (IsTypeCheckableTask) { + if (task->GetTaskType() != T::TaskType) { + task = nullptr; + } + } + + /* Return the task. */ + return task; + } + + template requires std::derived_from + void Delete(u32 index) { + /* Check that the task is valid. */ + if (!this->IsValid(index)) { + return; + } + + /* Delete the task. */ + std::destroy_at(this->GetPointer(index)); + + /* Mark the task as invalid. */ + m_valid[index] = false; + } + }; + +} diff --git a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_tasks.hpp b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_tasks.hpp index 9b8ef2566..fb9f423ba 100644 --- a/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_tasks.hpp +++ b/libraries/libstratosphere/source/htc/server/rpc/htc_rpc_tasks.hpp @@ -18,6 +18,8 @@ namespace ams::htc::server::rpc { + constexpr inline size_t MaxTaskCount = 0x48; + enum class RpcTaskCancelReason { None = 0, /* ... */