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,159 +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::scs {
namespace {
struct ResponseError {
ResponseHeader header;
u32 result;
};
struct ResponseProgramExited {
ResponseHeader header;
u64 process_id;
};
struct ResponseProgramLaunched {
ResponseHeader header;
u64 process_id;
};
constinit os::SdkMutex g_htcs_send_mutex;
}
std::scoped_lock<os::SdkMutex> CommandProcessor::MakeSendGuardBlock() {
return std::scoped_lock<os::SdkMutex>{g_htcs_send_mutex};
}
void CommandProcessor::Send(s32 socket, const void *data, size_t size) {
htcs::Send(socket, data, size, 0);
}
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. */
auto lk = MakeSendGuardBlock();
Send(socket, std::addressof(response), sizeof(response));
}
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. */
auto lk = MakeSendGuardBlock();
Send(socket, std::addressof(response), sizeof(response));
}
void CommandProcessor::SendExited(s32 socket, u64 id, u64 process_id) {
/* Build the response. */
const ResponseProgramExited response = {
.header = {
.id = id,
.response = Response_ProgramExited,
.body_size = sizeof(response) - sizeof(response.header),
},
.process_id = process_id,
};
/* Send the response. */
auto lk = MakeSendGuardBlock();
Send(socket, std::addressof(response), sizeof(response));
}
void CommandProcessor::SendJitDebug(s32 socket, u64 id) {
/* Build the response. */
const ResponseHeader response = {
.id = id,
.response = Response_JitDebug,
.body_size = 0,
};
/* Send the response. */
auto lk = MakeSendGuardBlock();
Send(socket, std::addressof(response), sizeof(response));
}
void CommandProcessor::SendLaunched(s32 socket, u64 id, u64 process_id) {
/* Build the response. */
const ResponseProgramLaunched response = {
.header = {
.id = id,
.response = Response_ProgramLaunched,
.body_size = sizeof(response) - sizeof(response.header),
},
.process_id = process_id,
};
/* Send the response. */
auto lk = MakeSendGuardBlock();
Send(socket, std::addressof(response), sizeof(response));
}
void CommandProcessor::OnProcessStart(u64 id, s32 socket, os::ProcessId process_id) {
SendLaunched(socket, id, process_id.value);
}
void CommandProcessor::OnProcessExit(u64 id, s32 socket, os::ProcessId process_id) {
SendExited(socket, id, process_id.value);
}
void CommandProcessor::OnProcessJitDebug(u64 id, s32 socket, os::ProcessId process_id) {
AMS_UNUSED(process_id);
SendJitDebug(socket, id);
}
void CommandProcessor::Initialize() {
/* Register our process event handlers. */
scs::RegisterCommonProcessEventHandler(OnProcessStart, OnProcessExit, OnProcessJitDebug);
}
bool CommandProcessor::ProcessCommand(const CommandHeader &header, const u8 *body, s32 socket) {
AMS_UNUSED(body);
switch (header.command) {
/* TODO: Support commands. */
default:
SendErrorResult(socket, header, scs::ResultUnknownCommand());
break;
}
return true;
}
}

View File

@@ -1,38 +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::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();
}
}

View File

@@ -1,398 +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::scs {
namespace {
struct SocketInfo {
u64 id;
s32 socket;
};
struct ProgramInfo {
os::ProcessId process_id;
u64 id;
s32 socket;
s32 info_id;
bool started;
bool jit_debug;
bool launched_by_cs;
};
constexpr inline auto MaxSocketInfo = 2;
constexpr inline auto MaxProgramInfo = 64;
class SocketInfoManager {
private:
SocketInfo m_infos[MaxSocketInfo]{};
int m_count{};
public:
constexpr SocketInfoManager() = default;
void Initialize() {
/* Clear our count. */
m_count = 0;
}
Result Register(s32 socket, u64 id) {
/* Check that the socket isn't already registered. */
for (auto i = 0; i < m_count; ++i) {
R_UNLESS(m_infos[i].socket != socket, scs::ResultNoSocket());
}
/* Check that we can allocate a new socket info. */
if (m_count >= MaxSocketInfo) {
/* NOTE: Nintendo aborts with this result here. */
R_ABORT_UNLESS(scs::ResultOutOfResource());
}
/* Create the new socket info. */
m_infos[m_count++] = {
.id = id,
.socket = socket,
};
R_SUCCEED();
}
void Unregister(s32 socket) {
/* Unregister the socket, if it's registered. */
for (auto i = 0; i < m_count; ++i) {
if (m_infos[i].socket == socket) {
/* Ensure that the valid socket infos remain in bounds. */
std::memcpy(m_infos + i, m_infos + i + 1, (m_count - (i + 1)) * sizeof(*m_infos));
/* Note that we now have one fewer socket info. */
--m_count;
break;
}
}
}
void InvokeHandler(ProcessEventHandler handler, os::ProcessId process_id) {
/* Invoke the handler on all our sockets. */
for (auto i = 0; i < m_count; ++i) {
handler(m_infos[i].id, m_infos[i].socket, process_id);
}
}
};
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;
}
const ProgramInfo *Find(os::ProcessId process_id) const {
/* Find a matching program. */
for (auto i = 0; i < m_count; ++i) {
if (m_infos[i].process_id == process_id) {
return std::addressof(m_infos[i]);
}
}
return nullptr;
}
bool Register(os::ProcessId process_id) {
/* Allocate an info id. */
const auto info_id = m_next_info_id++;
/* Check that we have space for the program. */
if (m_count >= MaxProgramInfo) {
return false;
}
/* Create the new program info. */
m_infos[m_count++] = {
.process_id = process_id,
.id = 0,
.socket = 0,
.info_id = info_id,
.started = false,
.jit_debug = false,
.launched_by_cs = false,
};
return true;
}
void Unregister(os::ProcessId process_id) {
/* Unregister the program, if it's registered. */
for (auto i = 0; i < m_count; ++i) {
if (m_infos[i].process_id == process_id) {
/* Ensure that the valid program infos remain in bounds. */
std::memcpy(m_infos + i, m_infos + i + 1, (m_count - (i + 1)) * sizeof(*m_infos));
/* Note that we now have one fewer program info. */
--m_count;
break;
}
}
}
void SetStarted(os::ProcessId process_id) {
/* Start the program. */
for (auto i = 0; i < m_count; ++i) {
if (m_infos[i].process_id == process_id) {
m_infos[i].started = true;
break;
}
}
}
void SetJitDebug(os::ProcessId process_id) {
/* Set the program as jit debug. */
for (auto i = 0; i < m_count; ++i) {
if (m_infos[i].process_id == process_id) {
m_infos[i].jit_debug = true;
break;
}
}
}
};
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;
constinit os::SdkMutex g_manager_mutex;
void ProcessExitEvent(const pm::ProcessEventInfo &event_info) {
/* Unregister the target environment definition. */
htc::tenv::UnregisterDefinitionFilePath(event_info.process_id);
/* Unregister program info. */
ProgramInfo program_info;
bool found = false;
{
std::scoped_lock lk(g_manager_mutex);
if (const ProgramInfo *pi = g_program_info_manager.Find(event_info.process_id); pi != nullptr) {
program_info = *pi;
found = true;
g_program_info_manager.Unregister(event_info.process_id);
}
}
/* If we found the program, handle callbacks. */
if (found) {
/* Invoke the common exit handler. */
if (program_info.launched_by_cs) {
g_common_exit_handler(program_info.id, program_info.socket, program_info.process_id);
}
/* Notify the process event. */
if (program_info.started) {
std::scoped_lock lk(g_manager_mutex);
g_socket_info_manager.InvokeHandler(g_common_exit_handler, program_info.process_id);
}
}
}
void ProcessStartedEvent(const pm::ProcessEventInfo &event_info) {
/* Start the program (registering it, if needed). */
{
std::scoped_lock lk(g_manager_mutex);
if (g_program_info_manager.Find(event_info.process_id) == nullptr) {
AMS_ABORT_UNLESS(g_program_info_manager.Register(event_info.process_id));
}
g_program_info_manager.SetStarted(event_info.process_id);
}
/* Handle callbacks. */
{
std::scoped_lock lk(g_manager_mutex);
g_socket_info_manager.InvokeHandler(g_common_start_handler, event_info.process_id);
}
}
void ProcessExceptionEvent(const pm::ProcessEventInfo &event_info) {
/* Find the program info. */
ProgramInfo program_info;
bool found = false;
{
std::scoped_lock lk(g_manager_mutex);
if (const ProgramInfo *pi = g_program_info_manager.Find(event_info.process_id); pi != nullptr) {
program_info = *pi;
found = true;
}
/* Set the program as jit debug. */
g_program_info_manager.SetJitDebug(event_info.process_id);
}
/* If we found the program, handle callbacks. */
if (found) {
/* Invoke the common exception handler. */
if (program_info.launched_by_cs) {
g_common_jit_debug_handler(program_info.id, program_info.socket, program_info.process_id);
}
/* Notify the process event. */
if (program_info.started) {
std::scoped_lock lk(g_manager_mutex);
g_socket_info_manager.InvokeHandler(g_common_jit_debug_handler, program_info.process_id);
}
}
}
void EventHandlerThread(void *) {
/* Get event observer. */
pgl::EventObserver observer;
R_ABORT_UNLESS(pgl::GetEventObserver(std::addressof(observer)));
/* Get the observer's event. */
os::SystemEventType shell_event;
R_ABORT_UNLESS(observer.GetSystemEvent(std::addressof(shell_event)));
/* Loop handling events. */
while (true) {
/* Wait for an event to come in. */
os::WaitSystemEvent(std::addressof(shell_event));
/* Loop processing event infos. */
while (true) {
/* Get the next event info. */
pm::ProcessEventInfo event_info;
if (R_FAILED(observer.GetProcessEventInfo(std::addressof(event_info)))) {
break;
}
/* Process the event. */
switch (event_info.GetProcessEvent()) {
case pm::ProcessEvent::Exited:
ProcessExitEvent(event_info);
break;
case pm::ProcessEvent::Started:
ProcessStartedEvent(event_info);
break;
case pm::ProcessEvent::Exception:
ProcessExceptionEvent(event_info);
break;
default:
break;
}
}
}
}
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::ResultArgumentCountOverflow) {
/* 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;
R_SUCCEED();
}
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;
}
Result RegisterSocket(s32 socket, u64 id) {
/* Acquire exclusive access to the socket info manager. */
std::scoped_lock lk(g_manager_mutex);
/* Register the socket. */
R_RETURN(g_socket_info_manager.Register(socket, id));
}
void UnregisterSocket(s32 socket) {
/* Acquire exclusive access to the socket info manager. */
std::scoped_lock lk(g_manager_mutex);
/* Unregister the socket. */
return g_socket_info_manager.Unregister(socket);
}
Result LaunchProgram(os::ProcessId *out, const ncm::ProgramLocation &loc, const void *args, size_t args_size, u32 process_flags) {
/* Set up the arguments. */
PrepareToLaunchProgram(loc.program_id, args, args_size);
/* Ensure arguments are managed correctly. */
ON_SCOPE_EXIT { FlushProgramArgument(loc.program_id); };
/* Launch the program. */
R_TRY(pgl::LaunchProgram(out, loc, process_flags | pm::LaunchFlags_SignalOnExit, 0));
R_SUCCEED();
}
Result SubscribeProcessEvent(s32 socket, bool is_register, u64 id);
}

View File

@@ -1,153 +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::scs {
namespace {
s32 CreateSocket() {
while (true) {
/* Try to create a socket. */
if (const auto desc = htcs::Socket(); desc >= 0) {
return desc;
}
/* Wait 100ms before trying again. */
os::SleepThread(TimeSpan::FromMilliSeconds(100));
}
}
s32 AcceptSocket(s32 listen_socket) {
htcs::SockAddrHtcs temp;
return htcs::Accept(listen_socket, std::addressof(temp));
}
s32 Bind(s32 socket, const htcs::HtcsPortName &port_name) {
/* Set up the bind address. */
htcs::SockAddrHtcs addr;
addr.family = htcs::HTCS_AF_HTCS;
addr.peer_name = htcs::GetPeerNameAny();
std::strcpy(addr.port_name.name, port_name.name);
/* Bind. */
return htcs::Bind(socket, std::addressof(addr));
}
htcs::ssize_t Receive(s32 socket, void *buffer, size_t size) {
u8 *dst = static_cast<u8 *>(buffer);
size_t received = 0;
while (received < size) {
const auto ret = htcs::Recv(socket, dst + received, size - received, 0);
if (ret <= 0) {
return ret;
}
received += ret;
}
return static_cast<htcs::ssize_t>(received);
}
bool ReceiveCommand(CommandHeader *header, void *buffer, size_t buffer_size, s32 socket) {
/* Receive the header. */
if (Receive(socket, header, sizeof(*header)) != sizeof(*header)) {
return false;
}
/* Check that the body will fit in the buffer. */
if (header->body_size >= buffer_size) {
return false;
}
/* Receive the body. */
if(Receive(socket, buffer, header->body_size) != static_cast<htcs::ssize_t>(header->body_size)) {
return false;
}
return true;
}
}
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() {
/* Loop servicing the shell server. */
while (true) {
/* Create a socket to listen on. */
const auto listen_socket = CreateSocket();
ON_SCOPE_EXIT { htcs::Close(listen_socket); };
/* Bind to the listen socket. */
if (Bind(listen_socket, m_port_name) != 0) {
continue;
}
/* Loop processing on our bound socket. */
while (true) {
/* Listen on the socket. */
if (const s32 listen_result = htcs::Listen(listen_socket, 0); listen_result != 0) {
/* TODO: logging. */
break;
}
/* Accept a socket. */
const s32 socket = AcceptSocket(listen_socket);
if (socket <= 0) {
/* TODO: logging. */
continue;
}
/* Ensure that the socket is cleaned up when we're done with it. */
ON_SCOPE_EXIT {
UnregisterSocket(socket);
htcs::Close(socket);
};
/* Loop servicing the socket. */
while (true) {
/* Receive a command header. */
CommandHeader header;
if (!ReceiveCommand(std::addressof(header), m_buffer, sizeof(m_buffer), socket)) {
break;
}
/* Process the command. */
if (!m_command_processor->ProcessCommand(header, m_buffer, socket)) {
break;
}
}
}
}
}
}

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