1+ /*
2+ * Copyright (c) 2018 Atmosphère-NX
3+ *
4+ * This program is free software; you can redistribute it and/or modify it
5+ * under the terms and conditions of the GNU General Public License,
6+ * version 2, as published by the Free Software Foundation.
7+ *
8+ * This program is distributed in the hope it will be useful, but WITHOUT
9+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11+ * more details.
12+ *
13+ * You should have received a copy of the GNU General Public License
14+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
15+ */
16+
17+ #include < mutex>
18+ #include < switch.h>
19+ #include " setsys_mitm_service.hpp"
20+
21+ #include " mitm_query_service.hpp"
22+ #include " debug.hpp"
23+
24+ static HosMutex g_version_mutex;
25+ static bool g_got_version = false ;
26+ static SetSysFirmwareVersion g_fw_version = {0 };
27+
28+ static Result _GetFirmwareVersion (SetSysFirmwareVersion *out) {
29+ std::lock_guard<HosMutex> lock (g_version_mutex);
30+ if (!g_got_version) {
31+ Result rc = setsysGetFirmwareVersion (&g_fw_version);
32+ if (R_FAILED (rc)) {
33+ return rc;
34+ }
35+
36+ /* Modify the output firmware version. */
37+ {
38+ u32 major, minor, micro;
39+ char display_version[sizeof (g_fw_version.display_version )] = {0 };
40+
41+ GetAtmosphereApiVersion (&major, &minor, µ, nullptr , nullptr );
42+ snprintf (display_version, sizeof (display_version), " %s (AMS %u.%u.%u)" , g_fw_version.display_version , major, minor, micro);
43+
44+ memcpy (g_fw_version.display_version , display_version, sizeof (g_fw_version.display_version ));
45+ }
46+
47+ g_got_version = true ;
48+ }
49+
50+ *out = g_fw_version;
51+ return 0 ;
52+ }
53+
54+ Result SetSysMitMService::dispatch (IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
55+ Result rc = 0xF601 ;
56+
57+ switch (static_cast <SetSysCmd>(cmd_id)) {
58+ case SetSysCmd::GetFirmwareVersion:
59+ rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version>(this , r, out_c, pointer_buffer, pointer_buffer_size);
60+ break ;
61+ case SetSysCmd::GetFirmwareVersion2:
62+ if (kernelAbove300 ()) {
63+ rc = WrapIpcCommandImpl<&SetSysMitMService::get_firmware_version2>(this , r, out_c, pointer_buffer, pointer_buffer_size);
64+ }
65+ break ;
66+ default :
67+ break ;
68+ }
69+
70+ return rc;
71+ }
72+
73+ void SetSysMitMService::postprocess (IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size) {
74+ /* No commands need postprocessing. */
75+ }
76+
77+ Result SetSysMitMService::handle_deferred () {
78+ /* This service is never deferrable. */
79+ return 0 ;
80+ }
81+
82+ std::tuple<Result> SetSysMitMService::get_firmware_version (OutPointerWithServerSize<SetSysFirmwareVersion, 0x1 > out) {
83+ if (out.num_elements != 1 ) {
84+ return {0xF601 };
85+ }
86+
87+ Result rc = _GetFirmwareVersion (out.pointer );
88+
89+ /* GetFirmwareVersion sanitizes these fields. */
90+ out.pointer ->revision_major = 0 ;
91+ out.pointer ->revision_minor = 0 ;
92+
93+ return {rc};
94+ }
95+
96+ std::tuple<Result> SetSysMitMService::get_firmware_version2 (OutPointerWithServerSize<SetSysFirmwareVersion, 0x1 > out) {
97+ if (out.num_elements != 1 ) {
98+ return {0xF601 };
99+ }
100+
101+ Result rc = _GetFirmwareVersion (out.pointer );
102+
103+ return {rc};
104+ }
0 commit comments