diff --git a/libraries/libstratosphere/include/stratosphere/scs/scs_command_processor.hpp b/libraries/libstratosphere/include/stratosphere/scs/scs_command_processor.hpp
index 1573754fa..adfe97b39 100644
--- a/libraries/libstratosphere/include/stratosphere/scs/scs_command_processor.hpp
+++ b/libraries/libstratosphere/include/stratosphere/scs/scs_command_processor.hpp
@@ -58,6 +58,7 @@ namespace ams::scs {
enum Response {
Response_None = 0,
Response_Success = 1,
+ Response_Error = 2,
/* ... */
};
public:
@@ -66,6 +67,17 @@ namespace ams::scs {
void Initialize();
public:
virtual bool ProcessCommand(const CommandHeader &header, const u8 *body, s32 socket);
+ protected:
+ static void SendSuccess(s32 socket, const CommandHeader &header);
+ static void SendErrorResult(s32 socket, const CommandHeader &header, Result result);
+ private:
+ static void SendErrorResult(s32 socket, u64 id, Result result);
+
+ static void OnProcessStart(u64 id, s32 socket, os::ProcessId process_id);
+ static void OnProcessExit(u64 id, s32 socket, os::ProcessId process_id);
+ static void OnProcessJitDebug(u64 id, s32 socket, os::ProcessId process_id);
};
+ os::SdkMutex &GetHtcsSendMutex();
+
}
diff --git a/libraries/libstratosphere/include/stratosphere/scs/scs_shell.hpp b/libraries/libstratosphere/include/stratosphere/scs/scs_shell.hpp
index b2aa9c425..9ba1caf22 100644
--- a/libraries/libstratosphere/include/stratosphere/scs/scs_shell.hpp
+++ b/libraries/libstratosphere/include/stratosphere/scs/scs_shell.hpp
@@ -20,7 +20,7 @@
namespace ams::scs {
- using ProcessEventHandler = void(*)(s64 command_id, s32 socket, os::ProcessId process_id);
+ using ProcessEventHandler = void(*)(u64 id, s32 socket, os::ProcessId process_id);
void InitializeShell();
@@ -29,6 +29,8 @@ namespace ams::scs {
bool RegisterSocket(s32 socket);
void UnregisterSocket(s32 socket);
- Result SubscribeProcessEvent(s32 socket, bool is_register, s64 command_id);
+ Result LaunchProgram(os::ProcessId *out, ncm::ProgramId program_id, const void *args, size_t args_size, u32 process_flags);
+
+ Result SubscribeProcessEvent(s32 socket, bool is_register, u64 id);
}
diff --git a/libraries/libstratosphere/source/boot2/boot2_api.cpp b/libraries/libstratosphere/source/boot2/boot2_api.cpp
index 6e2879b86..5c5c16ed7 100644
--- a/libraries/libstratosphere/source/boot2/boot2_api.cpp
+++ b/libraries/libstratosphere/source/boot2/boot2_api.cpp
@@ -397,6 +397,7 @@ namespace ams::boot2 {
/* Device whether to launch tma or htc. */
if (svc::IsKernelMesosphere() && IsHtcEnabled()) {
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Htc, ncm::StorageId::None), 0);
+ LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Cs, ncm::StorageId::None), 0);
} else {
LaunchProgram(nullptr, ncm::ProgramLocation::Make(ncm::SystemProgramId::Tma, ncm::StorageId::BuiltInSystem), 0);
}
diff --git a/libraries/libstratosphere/source/cs/cs_audio_server.cpp b/libraries/libstratosphere/source/cs/cs_audio_server.cpp
new file mode 100644
index 000000000..bd716364e
--- /dev/null
+++ b/libraries/libstratosphere/source/cs/cs_audio_server.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::cs {
+
+ void InitializeAudioServer() {
+ /* TODO: Support audio server. */
+ }
+
+}
diff --git a/libraries/libstratosphere/source/cs/cs_command_processor.cpp b/libraries/libstratosphere/source/cs/cs_command_processor.cpp
new file mode 100644
index 000000000..2fd4e9e6d
--- /dev/null
+++ b/libraries/libstratosphere/source/cs/cs_command_processor.cpp
@@ -0,0 +1,31 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::cs {
+
+ bool CommandProcessor::ProcessCommand(const CommandHeader &header, const u8 *body, s32 socket) {
+ switch (header.command) {
+ /* TODO: Command support. */
+ default:
+ scs::CommandProcessor::ProcessCommand(header, body, socket);
+ break;
+ }
+
+ return true;
+ }
+
+}
diff --git a/libraries/libstratosphere/source/cs/cs_hid_server.cpp b/libraries/libstratosphere/source/cs/cs_hid_server.cpp
new file mode 100644
index 000000000..2aabab5df
--- /dev/null
+++ b/libraries/libstratosphere/source/cs/cs_hid_server.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::cs {
+
+ void InitializeHidServer() {
+ /* TODO: Support hid redirection server. */
+ }
+
+}
diff --git a/libraries/libstratosphere/source/cs/cs_remote_video_server.cpp b/libraries/libstratosphere/source/cs/cs_remote_video_server.cpp
new file mode 100644
index 000000000..f00454fa0
--- /dev/null
+++ b/libraries/libstratosphere/source/cs/cs_remote_video_server.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::cs {
+
+ void InitializeRemoteVideoServer() {
+ /* TODO: Support remote video server. */
+ }
+
+}
diff --git a/libraries/libstratosphere/source/cs/cs_target_io_server.cpp b/libraries/libstratosphere/source/cs/cs_target_io_server.cpp
new file mode 100644
index 000000000..284b8fb04
--- /dev/null
+++ b/libraries/libstratosphere/source/cs/cs_target_io_server.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::cs {
+
+ void InitializeTargetIoServer() {
+ /* Launch target io server. */
+ os::ProcessId process_id;
+ scs::LaunchProgram(std::addressof(process_id), ncm::SystemProgramId::DevServer, nullptr, 0, 0);
+ }
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/htc_tenv.cpp b/libraries/libstratosphere/source/htc/tenv/htc_tenv.cpp
new file mode 100644
index 000000000..4e31262a3
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/htc_tenv.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 .
+ */
+#include
+#include "impl/htc_tenv_allocator.hpp"
+
+namespace ams::htc::tenv {
+
+ void Initialize(AllocateFunction allocate, DeallocateFunction deallocate) {
+ /* Initialize the library allocator. */
+ impl::InitializeAllocator(allocate, deallocate);
+ }
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.cpp b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.cpp
new file mode 100644
index 000000000..ad316748e
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+#include
+#include "htc_tenv_service.hpp"
+
+namespace ams::htc::tenv {
+
+ Result Service::GetVariable(sf::Out out_size, const sf::OutBuffer &out_buffer, const htc::tenv::VariableName &name) {
+ /* TODO */
+ AMS_ABORT("Service::GetVariable");
+ }
+
+ Result Service::GetVariableLength(sf::Out out_size,const htc::tenv::VariableName &name) {
+ /* TODO */
+ AMS_ABORT("Service::GetVariableLength");
+ }
+
+ Result Service::WaitUntilVariableAvailable(s64 timeout_ms) {
+ /* TODO */
+ AMS_ABORT("Service::WaitUntilVariableAvailable");
+ }
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.hpp b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.hpp
new file mode 100644
index 000000000..9ce3230bb
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service.hpp
@@ -0,0 +1,33 @@
+/*
+ * 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
+
+namespace ams::htc::tenv {
+
+ class Service {
+ private:
+ os::ProcessId m_process_id;
+ public:
+ constexpr Service(os::ProcessId pid) : m_process_id(pid) { /* ... */ }
+ public:
+ Result GetVariable(sf::Out out_size, const sf::OutBuffer &out_buffer, const htc::tenv::VariableName &name);
+ Result GetVariableLength(sf::Out out_size,const htc::tenv::VariableName &name);
+ Result WaitUntilVariableAvailable(s64 timeout_ms);
+ };
+ static_assert(htc::tenv::IsIService);
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/htc_tenv_service_manager.cpp b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service_manager.cpp
new file mode 100644
index 000000000..1a954712f
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/htc_tenv_service_manager.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 .
+ */
+#include
+#include "impl/htc_tenv_allocator.hpp"
+#include "htc_tenv_service.hpp"
+
+namespace ams::htc::tenv {
+
+ Result ServiceManager::GetServiceInterface(sf::Out> out, const sf::ClientProcessId &process_id) {
+ *out = impl::SfObjectFactory::CreateSharedEmplaced(process_id.GetValue());
+ return ResultSuccess();
+ }
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.cpp b/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.cpp
new file mode 100644
index 000000000..93c2cc86b
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.cpp
@@ -0,0 +1,56 @@
+/*
+ * 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 .
+ */
+#include
+#include "htc_tenv_allocator.hpp"
+
+namespace ams::htc::tenv::impl {
+
+ namespace {
+
+ constinit AllocateFunction g_allocate = nullptr;
+ constinit DeallocateFunction g_deallocate = nullptr;
+
+ }
+
+ void InitializeAllocator(AllocateFunction allocate, DeallocateFunction deallocate) {
+ /* Check that we don't already have allocator functions. */
+ AMS_ASSERT(g_allocate == nullptr);
+ AMS_ASSERT(g_deallocate == nullptr);
+
+ /* Set our allocator functions. */
+ g_allocate = allocate;
+ g_deallocate = deallocate;
+
+ /* Check that we have allocator functions. */
+ AMS_ASSERT(g_allocate != nullptr);
+ AMS_ASSERT(g_deallocate != nullptr);
+ }
+
+ void *Allocate(size_t size) {
+ /* Check that we have an allocator. */
+ AMS_ASSERT(g_allocate != nullptr);
+
+ return g_allocate(size);
+ }
+
+ void Deallocate(void *p, size_t size) {
+ /* Check that we have a deallocator. */
+ AMS_ASSERT(g_deallocate != nullptr);
+
+ return g_deallocate(p, size);
+ }
+
+}
diff --git a/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.hpp b/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.hpp
new file mode 100644
index 000000000..f48f2056a
--- /dev/null
+++ b/libraries/libstratosphere/source/htc/tenv/impl/htc_tenv_allocator.hpp
@@ -0,0 +1,42 @@
+/*
+ * 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
+
+namespace ams::htc::tenv::impl {
+
+ void InitializeAllocator(AllocateFunction allocate, DeallocateFunction deallocate);
+
+ void *Allocate(size_t size);
+ void Deallocate(void *p, size_t size);
+
+ class SfAllocator {
+ public:
+ constexpr ALWAYS_INLINE SfAllocator() { /* ... */ }
+
+ void *Allocate(size_t size) {
+ return ::ams::htc::tenv::impl::Allocate(size);
+ }
+
+ void Deallocate(void *p, size_t size) {
+ return ::ams::htc::tenv::impl::Deallocate(p, size);
+ }
+ };
+
+ using SfPolicy = sf::StatelessAllocationPolicy;
+ using SfObjectFactory = sf::ObjectFactory;
+
+}
diff --git a/libraries/libstratosphere/source/scs/scs_command_processor.cpp b/libraries/libstratosphere/source/scs/scs_command_processor.cpp
new file mode 100644
index 000000000..b3da75937
--- /dev/null
+++ b/libraries/libstratosphere/source/scs/scs_command_processor.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::scs {
+
+ namespace {
+
+ struct ResponseError {
+ ResponseHeader header;
+ u32 result;
+ };
+
+ constinit os::SdkMutex g_htcs_send_mutex;
+
+ }
+
+ os::SdkMutex &GetHtcsSendMutex() {
+ return g_htcs_send_mutex;
+ }
+
+ void CommandProcessor::SendSuccess(s32 socket, const CommandHeader &header) {
+ /* Build the response. */
+ const ResponseHeader response = {
+ .id = header.id,
+ .response = Response_Success,
+ .body_size = 0,
+ };
+
+ /* Send the response. */
+ std::scoped_lock lk(GetHtcsSendMutex());
+ htcs::Send(socket, std::addressof(response), sizeof(response), 0);
+ }
+
+ void CommandProcessor::SendErrorResult(s32 socket, const CommandHeader &header, Result result) {
+ return SendErrorResult(socket, header.id, result);
+ }
+
+ void CommandProcessor::SendErrorResult(s32 socket, u64 id, Result result) {
+ /* Build the response. */
+ const ResponseError response = {
+ .header = {
+ .id = id,
+ .response = Response_Error,
+ .body_size = sizeof(response) - sizeof(response.header),
+ },
+ .result = result.GetValue(),
+ };
+
+ /* Send the response. */
+ std::scoped_lock lk(GetHtcsSendMutex());
+ htcs::Send(socket, std::addressof(response), sizeof(response), 0);
+ }
+
+ void CommandProcessor::OnProcessStart(u64 id, s32 socket, os::ProcessId process_id) {
+ /* TODO */
+ AMS_ABORT("CommandProcessor::OnProcessStart");
+ }
+
+ void CommandProcessor::OnProcessExit(u64 id, s32 socket, os::ProcessId process_id) {
+ /* TODO */
+ AMS_ABORT("CommandProcessor::OnProcessExit");
+ }
+
+ void CommandProcessor::OnProcessJitDebug(u64 id, s32 socket, os::ProcessId process_id) {
+ /* TODO */
+ AMS_ABORT("CommandProcessor::OnProcessJitDebug");
+ }
+
+ void CommandProcessor::Initialize() {
+ /* Register our process event handlers. */
+ scs::RegisterCommonProcessEventHandler(OnProcessStart, OnProcessExit, OnProcessJitDebug);
+ }
+
+ bool CommandProcessor::ProcessCommand(const CommandHeader &header, const u8 *body, s32 socket) {
+ switch (header.command) {
+ /* TODO: Support commands. */
+ default:
+ SendErrorResult(socket, header, scs::ResultUnknownCommand());
+ break;
+ }
+
+ return true;
+ }
+
+}
diff --git a/libraries/libstratosphere/source/scs/scs_server_manager.cpp b/libraries/libstratosphere/source/scs/scs_server_manager.cpp
new file mode 100644
index 000000000..0a9fd2d94
--- /dev/null
+++ b/libraries/libstratosphere/source/scs/scs_server_manager.cpp
@@ -0,0 +1,38 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::scs {
+
+ namespace {
+
+ ServerManager g_server_manager;
+
+ }
+
+ ServerManager *GetServerManager() {
+ return std::addressof(g_server_manager);
+ }
+
+ void StartServer() {
+ /* Start the server. */
+ g_server_manager.ResumeProcessing();
+
+ /* Loop processing the server. */
+ g_server_manager.LoopProcess();
+ }
+
+}
diff --git a/libraries/libstratosphere/source/scs/scs_shell.cpp b/libraries/libstratosphere/source/scs/scs_shell.cpp
new file mode 100644
index 000000000..0f511064f
--- /dev/null
+++ b/libraries/libstratosphere/source/scs/scs_shell.cpp
@@ -0,0 +1,152 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::scs {
+
+ namespace {
+
+ struct SocketInfo {
+ u64 id;
+ s32 socket;
+ };
+
+ struct ProgramInfo {
+ os::ProcessId process_id;
+ u64 id;
+ s32 socket;
+ s32 info_id;
+ bool _18;
+ bool _19;
+ bool _1A;
+ };
+
+ constexpr inline auto MaxSocketInfo = 2;
+ constexpr inline auto MaxProgramInfo = 64;
+
+ class SocketInfoManager {
+ private:
+ SocketInfo m_infos[MaxProgramInfo];
+ int m_count;
+ public:
+ constexpr SocketInfoManager() = default;
+
+ void Initialize() {
+ /* Clear our count. */
+ m_count = 0;
+ }
+ };
+
+ class ProgramInfoManager {
+ private:
+ s32 m_next_info_id;
+ ProgramInfo m_infos[MaxProgramInfo];
+ int m_count;
+ public:
+ constexpr ProgramInfoManager() = default;
+
+ void Initialize() {
+ /* Reset our next id. */
+ m_next_info_id = 1;
+
+ /* Clear our count. */
+ m_count = 0;
+ }
+ };
+
+ alignas(os::ThreadStackAlignment) constinit u8 g_thread_stack[os::MemoryPageSize];
+ constinit os::ThreadType g_thread;
+
+ constinit ProcessEventHandler g_common_start_handler;
+ constinit ProcessEventHandler g_common_exit_handler;
+ constinit ProcessEventHandler g_common_jit_debug_handler;
+
+ constinit SocketInfoManager g_socket_info_manager;
+ constinit ProgramInfoManager g_program_info_manager;
+
+ void EventHandlerThread(void *) {
+ /* TODO */
+ AMS_ABORT("scs::EventHandlerThread");
+ }
+
+ void StartEventHandlerThread() {
+ /* Create the handler thread. */
+ R_ABORT_UNLESS(os::CreateThread(std::addressof(g_thread), EventHandlerThread, nullptr, g_thread_stack, sizeof(g_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(scs, ShellEventHandler)));
+
+ /* Set the handler thread's name. */
+ os::SetThreadNamePointer(std::addressof(g_thread), AMS_GET_SYSTEM_THREAD_NAME(scs, ShellEventHandler));
+
+ /* Start the handler thread. */
+ os::StartThread(std::addressof(g_thread));
+ }
+
+ Result PrepareToLaunchProgram(ncm::ProgramId program_id, const void *args, size_t args_size) {
+ /* Set the arguments. */
+ R_TRY_CATCH(ldr::SetProgramArgument(program_id, args, args_size)) {
+ R_CATCH(ldr::ResultTooManyArguments) {
+ /* There are too many arguments already registered. Flush the arguments queue. */
+ R_TRY(ldr::FlushArguments());
+
+ /* Try again. */
+ R_TRY(ldr::SetProgramArgument(program_id, args, args_size));
+ }
+ } R_END_TRY_CATCH;
+
+ return ResultSuccess();
+ }
+
+ void FlushProgramArgument(ncm::ProgramId program_id) {
+ /* Ensure there are no arguments for the program. */
+ ldr::SetProgramArgument(program_id, "", 1);
+ }
+
+ }
+
+ void InitializeShell() {
+ /* Initialize our managers. */
+ g_socket_info_manager.Initialize();
+ g_program_info_manager.Initialize();
+
+ /* Start our event handler. */
+ StartEventHandlerThread();
+ }
+
+ void RegisterCommonProcessEventHandler(ProcessEventHandler on_start, ProcessEventHandler on_exit, ProcessEventHandler on_jit_debug) {
+ g_common_start_handler = on_start;
+ g_common_exit_handler = on_exit;
+ g_common_jit_debug_handler = on_jit_debug;
+ }
+
+ bool RegisterSocket(s32 socket);
+ void UnregisterSocket(s32 socket);
+
+ Result LaunchProgram(os::ProcessId *out, ncm::ProgramId program_id, const void *args, size_t args_size, u32 process_flags) {
+ /* Set up the arguments. */
+ PrepareToLaunchProgram(program_id, args, args_size);
+
+ /* Ensure arguments are managed correctly. */
+ ON_SCOPE_EXIT { FlushProgramArgument(program_id); };
+
+ /* Launch the program. */
+ const ncm::ProgramLocation loc = ncm::ProgramLocation::Make(program_id, ncm::StorageId::BuiltInSystem);
+ R_TRY(pgl::LaunchProgram(out, loc, process_flags | pm::LaunchFlags_SignalOnExit, 0));
+
+ return ResultSuccess();
+ }
+
+ Result SubscribeProcessEvent(s32 socket, bool is_register, u64 id);
+
+}
diff --git a/libraries/libstratosphere/source/scs/scs_shell_server.cpp b/libraries/libstratosphere/source/scs/scs_shell_server.cpp
new file mode 100644
index 000000000..286fa31d9
--- /dev/null
+++ b/libraries/libstratosphere/source/scs/scs_shell_server.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::scs {
+
+ void ShellServer::Initialize(const char *port_name, void *stack, size_t stack_size, CommandProcessor *command_processor) {
+ /* Set our variables. */
+ m_command_processor = command_processor;
+ std::strcpy(m_port_name.name, port_name);
+
+ /* Create our thread. */
+ R_ABORT_UNLESS(os::CreateThread(std::addressof(m_thread), ThreadEntry, this, stack, stack_size, AMS_GET_SYSTEM_THREAD_PRIORITY(scs, ShellServer)));
+
+ /* Set our thread's name. */
+ os::SetThreadNamePointer(std::addressof(m_thread), AMS_GET_SYSTEM_THREAD_NAME(scs, ShellServer));
+ }
+
+ void ShellServer::Start() {
+ os::StartThread(std::addressof(m_thread));
+ }
+
+ void ShellServer::DoShellServer() {
+ /* TODO */
+ AMS_ABORT("ShellServer::DoShellServer");
+ }
+
+}
diff --git a/libraries/libstratosphere/source/scs/scs_tenv.cpp b/libraries/libstratosphere/source/scs/scs_tenv.cpp
new file mode 100644
index 000000000..7569517d8
--- /dev/null
+++ b/libraries/libstratosphere/source/scs/scs_tenv.cpp
@@ -0,0 +1,52 @@
+/*
+ * 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 .
+ */
+#include
+
+namespace ams::scs {
+
+ namespace {
+
+ alignas(os::MemoryPageSize) constinit u8 g_tenv_heap_storage[48_KB];
+ constinit lmem::HeapHandle g_tenv_heap_handle = nullptr;
+ constinit os::SdkMutex g_mutex;
+
+ void InitializeExpHeap() {
+ std::scoped_lock lk(g_mutex);
+ g_tenv_heap_handle = lmem::CreateExpHeap(g_tenv_heap_storage, sizeof(g_tenv_heap_storage), lmem::CreateOption_None);
+ }
+
+ void *Allocate(size_t size) {
+ std::scoped_lock lk(g_mutex);
+ void *mem = lmem::AllocateFromExpHeap(g_tenv_heap_handle, size);
+ return mem;
+ }
+
+ void Deallocate(void *p, size_t size) {
+ std::scoped_lock lk(g_mutex);
+ lmem::FreeToExpHeap(g_tenv_heap_handle, p);
+ }
+
+ }
+
+ void InitializeTenvServiceManager() {
+ /* Initialize the tenv heap. */
+ InitializeExpHeap();
+
+ /* Initialize the tenv library. */
+ htc::tenv::Initialize(Allocate, Deallocate);
+ }
+
+}
diff --git a/libraries/libvapours/include/vapours/results.hpp b/libraries/libvapours/include/vapours/results.hpp
index ad89ea157..7786f7f23 100644
--- a/libraries/libvapours/include/vapours/results.hpp
+++ b/libraries/libvapours/include/vapours/results.hpp
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -55,6 +56,7 @@
#include
#include
#include
+#include
#include
#include
#include
diff --git a/libraries/libvapours/include/vapours/results/cs_results.hpp b/libraries/libvapours/include/vapours/results/cs_results.hpp
new file mode 100644
index 000000000..0c1a67ab4
--- /dev/null
+++ b/libraries/libvapours/include/vapours/results/cs_results.hpp
@@ -0,0 +1,28 @@
+/*
+ * 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
+
+namespace ams::cs {
+
+ R_DEFINE_NAMESPACE_RESULT_MODULE(204);
+
+ R_DEFINE_ERROR_RESULT(UnknownCommand, 2);
+ R_DEFINE_ERROR_RESULT(OutOfResource, 4);
+ R_DEFINE_ERROR_RESULT(NoSocket, 7);
+
+}
diff --git a/libraries/libvapours/include/vapours/results/scs_results.hpp b/libraries/libvapours/include/vapours/results/scs_results.hpp
new file mode 100644
index 000000000..8981847a8
--- /dev/null
+++ b/libraries/libvapours/include/vapours/results/scs_results.hpp
@@ -0,0 +1,28 @@
+/*
+ * 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
+
+namespace ams::scs {
+
+ R_DEFINE_NAMESPACE_RESULT_MODULE(204);
+
+ R_DEFINE_ERROR_RESULT(UnknownCommand, 2);
+ R_DEFINE_ERROR_RESULT(OutOfResource, 4);
+ R_DEFINE_ERROR_RESULT(NoSocket, 7);
+
+}
diff --git a/stratosphere/cs/source/cs_main.cpp b/stratosphere/cs/source/cs_main.cpp
index aa0dd182d..479f82012 100644
--- a/stratosphere/cs/source/cs_main.cpp
+++ b/stratosphere/cs/source/cs_main.cpp
@@ -65,26 +65,30 @@ namespace ams::cs {
namespace {
- alignas(os::ThreadStackAlignment) u8 g_shell_stack[4_KB];
- alignas(os::ThreadStackAlignment) u8 g_runner_stack[4_KB];
+ alignas(os::ThreadStackAlignment) constinit u8 g_shell_stack[4_KB];
+ alignas(os::ThreadStackAlignment) constinit u8 g_runner_stack[4_KB];
- alignas(os::MemoryPageSize) u8 g_heap_memory[32_KB];
+ alignas(os::MemoryPageSize) constinit u8 g_heap_memory[32_KB];
- alignas(0x40) u8 g_htcs_buffer[1_KB];
+ alignas(0x40) constinit u8 g_htcs_buffer[1_KB];
- lmem::HeapHandle g_heap_handle;
+ constinit os::SdkMutex g_heap_mutex;
+ constinit lmem::HeapHandle g_heap_handle;
void *Allocate(size_t size) {
+ std::scoped_lock lk(g_heap_mutex);
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
return mem;
}
void Deallocate(void *p, size_t size) {
+ std::scoped_lock lk(g_heap_mutex);
lmem::FreeToExpHeap(g_heap_handle, p);
}
void InitializeHeap() {
- g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_ThreadSafe);
+ std::scoped_lock lk(g_heap_mutex);
+ g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
}
}