diff --git a/stratosphere/set_mitm/source/setmitm_main.cpp b/stratosphere/set_mitm/source/setmitm_main.cpp index 3fea764dd..bfba144e4 100644 --- a/stratosphere/set_mitm/source/setmitm_main.cpp +++ b/stratosphere/set_mitm/source/setmitm_main.cpp @@ -85,7 +85,7 @@ int main(int argc, char **argv) auto server_manager = new SetMitmManager(1); /* Create set:sys mitm. */ - AddMitmServerToManager(server_manager, "set:sys", 4); + AddMitmServerToManager(server_manager, "set:sys", 60); /* Connect to set:sys. */ { diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.cpp b/stratosphere/set_mitm/source/setsys_firmware_version.cpp new file mode 100644 index 000000000..b37c1726f --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_firmware_version.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018 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 + +#include "setsys_firmware_version.hpp" + +static HosMutex g_version_mutex; +static bool g_got_version = false; +static SetSysFirmwareVersion g_fw_version = {0}; + +Result VersionManager::GetFirmwareVersion(u64 title_id, SetSysFirmwareVersion *out) { + std::scoped_lock lock(g_version_mutex); + if (!g_got_version) { + Result rc = setsysGetFirmwareVersion(&g_fw_version); + if (R_FAILED(rc)) { + return rc; + } + + /* Modify the output firmware version. */ + { + u32 major, minor, micro; + char display_version[sizeof(g_fw_version.display_version)] = {0}; + + GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); + snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); + + memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); + } + + g_got_version = true; + } + + /* Report atmosphere string to qlaunch, maintenance and nothing else. */ + if (title_id == 0x0100000000001000ULL || title_id == 0x0100000000001015ULL) { + *out = g_fw_version; + return 0; + } else { + return setsysGetFirmwareVersion(out); + } +} \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_firmware_version.hpp b/stratosphere/set_mitm/source/setsys_firmware_version.hpp new file mode 100644 index 000000000..de035ed92 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_firmware_version.hpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018 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 + +class VersionManager { + public: + static Result GetFirmwareVersion(u64 title_id, SetSysFirmwareVersion *out); +}; diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.cpp b/stratosphere/set_mitm/source/setsys_mitm_service.cpp index 60e1c5e2c..33db6bef0 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.cpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.cpp @@ -15,45 +15,17 @@ */ #include +#include #include #include "setsys_mitm_service.hpp" - -static HosMutex g_version_mutex; -static bool g_got_version = false; -static SetSysFirmwareVersion g_fw_version = {0}; - -static Result _GetFirmwareVersion(SetSysFirmwareVersion *out) { - std::scoped_lock lock(g_version_mutex); - if (!g_got_version) { - Result rc = setsysGetFirmwareVersion(&g_fw_version); - if (R_FAILED(rc)) { - return rc; - } - - /* Modify the output firmware version. */ - { - u32 major, minor, micro; - char display_version[sizeof(g_fw_version.display_version)] = {0}; - - GetAtmosphereApiVersion(&major, &minor, µ, nullptr, nullptr); - snprintf(display_version, sizeof(display_version), "%s (AMS %u.%u.%u)", g_fw_version.display_version, major, minor, micro); - - memcpy(g_fw_version.display_version, display_version, sizeof(g_fw_version.display_version)); - } - - g_got_version = true; - } - - *out = g_fw_version; - return 0; -} +#include "setsys_firmware_version.hpp" void SetSysMitmService::PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx) { /* No commands need postprocessing. */ } -Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize out) { - Result rc = _GetFirmwareVersion(out.pointer); +Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize out) { + Result rc = VersionManager::GetFirmwareVersion(this->title_id, out.pointer); /* GetFirmwareVersion sanitizes these fields. */ if (R_SUCCEEDED(rc)) { @@ -64,6 +36,48 @@ Result SetSysMitmService::GetFirmwareVersion(OutPointerWithServerSize out) { - return _GetFirmwareVersion(out.pointer); +Result SetSysMitmService::GetFirmwareVersion2(OutPointerWithServerSize out) { + return VersionManager::GetFirmwareVersion(this->title_id, out.pointer); +} + +Result SetSysMitmService::GetSettingsItemValueSize(Out out_size, InPointer in_name, InPointer in_key) { + char name[SET_MAX_NAME_SIZE] = {0}; + char key[SET_MAX_NAME_SIZE] = {0}; + + if (in_name.num_elements < SET_MAX_NAME_SIZE) { + strncpy(name, in_name.pointer, in_name.num_elements); + } else { + strncpy(name, in_name.pointer, SET_MAX_NAME_SIZE-1); + } + + if (in_key.num_elements < SET_MAX_NAME_SIZE) { + strncpy(key, in_key.pointer, in_key.num_elements); + } else { + strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); + } + + return setsysGetSettingsItemValueSize(name, key, out_size.GetPointer()); +} + +Result SetSysMitmService::GetSettingsItemValue(Out out_size, OutBuffer out_value, InPointer in_name, InPointer in_key) { + char name[SET_MAX_NAME_SIZE] = {0}; + char key[SET_MAX_NAME_SIZE] = {0}; + + if (in_name.num_elements < SET_MAX_NAME_SIZE) { + strncpy(name, in_name.pointer, in_name.num_elements); + } else { + strncpy(name, in_name.pointer, SET_MAX_NAME_SIZE-1); + } + + if (in_key.num_elements < SET_MAX_NAME_SIZE) { + strncpy(key, in_key.pointer, in_key.num_elements); + } else { + strncpy(key, in_key.pointer, SET_MAX_NAME_SIZE-1); + } + + return setsysGetSettingsItemValue(name, key, out_value.buffer, out_value.num_elements); +} + +Result SetSysMitmService::GetEdid(OutPointerWithServerSize out) { + return setsysGetEdidFwd(this->forward_service.get(), out.pointer); } \ No newline at end of file diff --git a/stratosphere/set_mitm/source/setsys_mitm_service.hpp b/stratosphere/set_mitm/source/setsys_mitm_service.hpp index 65a172175..36d12e064 100644 --- a/stratosphere/set_mitm/source/setsys_mitm_service.hpp +++ b/stratosphere/set_mitm/source/setsys_mitm_service.hpp @@ -18,9 +18,17 @@ #include #include +#include "setsys_shim.h" + enum SetSysCmd : u32 { SetSysCmd_GetFirmwareVersion = 3, SetSysCmd_GetFirmwareVersion2 = 4, + SetSysCmd_GetSettingsItemValueSize = 37, + SetSysCmd_GetSettingsItemValue = 38, + + /* Commands for which set:sys *must* act as a passthrough. */ + /* TODO: Solve the relevant IPC detection problem. */ + SetSysCmd_GetEdid = 41, }; class SetSysMitmService : public IMitmServiceObject { @@ -30,8 +38,8 @@ class SetSysMitmService : public IMitmServiceObject { } static bool ShouldMitm(u64 pid, u64 tid) { - /* Only MitM qlaunch, maintenance. */ - return tid == 0x0100000000001000ULL || tid == 0x0100000000001015ULL; + /* Mitm everything. */ + return true; } static void PostProcess(IMitmServiceObject *obj, IpcResponseContext *ctx); @@ -40,9 +48,18 @@ class SetSysMitmService : public IMitmServiceObject { /* Overridden commands. */ Result GetFirmwareVersion(OutPointerWithServerSize out); Result GetFirmwareVersion2(OutPointerWithServerSize out); + Result GetSettingsItemValueSize(Out out_size, InPointer name, InPointer key); + Result GetSettingsItemValue(Out out_size, OutBuffer out_value, InPointer name, InPointer key); + + /* Forced passthrough commands. */ + Result GetEdid(OutPointerWithServerSize out); public: DEFINE_SERVICE_DISPATCH_TABLE { MakeServiceCommandMeta(), MakeServiceCommandMeta(), + MakeServiceCommandMeta(), + MakeServiceCommandMeta(), + + MakeServiceCommandMeta(), }; }; diff --git a/stratosphere/set_mitm/source/setsys_shim.c b/stratosphere/set_mitm/source/setsys_shim.c new file mode 100644 index 000000000..4edae7004 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_shim.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018 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 "setsys_shim.h" + +/* Command forwarders. */ +Result setsysGetEdidFwd(Service* s, SetSysEdid* out) { + IpcCommand c; + ipcInitialize(&c); + ipcAddRecvStatic(&c, out, sizeof(*out), 0); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 41; + + Result rc = serviceIpcDispatch(s); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(s, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} diff --git a/stratosphere/set_mitm/source/setsys_shim.h b/stratosphere/set_mitm/source/setsys_shim.h new file mode 100644 index 000000000..6f475ea46 --- /dev/null +++ b/stratosphere/set_mitm/source/setsys_shim.h @@ -0,0 +1,23 @@ +/** + * @file setsys_shim.h + * @brief System Settings Services (set:sys) IPC wrapper. To be merged into libnx, eventually. + * @author SciresM + * @copyright libnx Authors + */ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + char edid[0x100]; +} SetSysEdid; + +/* Command forwarders. */ +Result setsysGetEdidFwd(Service* s, SetSysEdid* out); + +#ifdef __cplusplus +} +#endif \ No newline at end of file