From 0d8c3ee1d31b907417446bd86e41440a419253dd Mon Sep 17 00:00:00 2001 From: Subv Date: Sat, 11 Apr 2020 19:20:51 -0500 Subject: [PATCH] Services/APT: Implemented the Store/LoadSysMenuArg functions. They are called by the Home Menu during initialization. These functions will not see much use until we actually implement application jumping and system rebooting. For now we just need them to prevent some unmapped reads in the Home Menu due to the static buffers not being properly set up. --- src/core/hle/service/apt/apt.cpp | 31 ++++++++++++++++++++++++++++++ src/core/hle/service/apt/apt.h | 30 +++++++++++++++++++++++++++++ src/core/hle/service/apt/apt_s.cpp | 4 ++-- src/core/hle/service/apt/apt_u.cpp | 4 ++-- 4 files changed, 65 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index f7fb0660f..a46b96d5c 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -650,6 +650,37 @@ void Module::APTInterface::CloseLibraryApplet(Kernel::HLERequestContext& ctx) { rb.Push(apt->applet_manager->CloseLibraryApplet(std::move(object), std::move(buffer))); } +void Module::APTInterface::LoadSysMenuArg(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x36, 1, 0); // 0x00360040 + const auto size = std::min(std::size_t{rp.Pop()}, SysMenuArgSize); + + // This service function does not clear the buffer. + + std::vector buffer(size); + std::copy_n(apt->sys_menu_arg_buffer.cbegin(), size, buffer.begin()); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushStaticBuffer(std::move(buffer), 0); + + LOG_DEBUG(Service_APT, "called"); +} + +void Module::APTInterface::StoreSysMenuArg(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x37, 1, 2); // 0x00370042 + const auto size = std::min(std::size_t{rp.Pop()}, SysMenuArgSize); + const auto& buffer = rp.PopStaticBuffer(); + + ASSERT_MSG(buffer.size() >= size, "Buffer too small to hold requested data"); + + std::copy_n(buffer.cbegin(), size, apt->sys_menu_arg_buffer.begin()); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_DEBUG(Service_APT, "called"); +} + void Module::APTInterface::SendCaptureBufferInfo(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x40, 1, 2); // 0x00400042 u32 size = rp.Pop(); diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index 2e2c219cd..a2158c217 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include "common/common_funcs.h" @@ -42,6 +43,8 @@ struct CaptureBufferInfo { }; static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has incorrect size"); +constexpr std::size_t SysMenuArgSize = 0x40; + enum class StartupArgumentType : u32 { OtherApp = 0, Restart = 1, @@ -518,6 +521,32 @@ public: */ void CloseLibraryApplet(Kernel::HLERequestContext& ctx); + /** + * APT::LoadSysMenuArg service function + * Inputs: + * 0 : Command header [0x00360040] + * 1 : Buffer size + * Outputs: + * 0 : Header code + * 1 : Result code + * 64 : Size << 14 | 2 + * 65 : void* Output Buffer + */ + void LoadSysMenuArg(Kernel::HLERequestContext& ctx); + + /** + * APT::StoreSysMenuArg service function + * Inputs: + * 0 : Command header [0x00370042] + * 1 : Buffer size + * 2 : (Size << 14) | 2 + * 3 : Input buffer virtual address + * Outputs: + * 0 : Header code + * 1 : Result code + */ + void StoreSysMenuArg(Kernel::HLERequestContext& ctx); + /** * APT::SendCaptureBufferInfo service function * Inputs: @@ -625,6 +654,7 @@ private: u8 unknown_ns_state_field = 0; std::vector screen_capture_buffer; + std::array sys_menu_arg_buffer; ScreencapPostPermission screen_capture_post_permission = ScreencapPostPermission::CleanThePermission; // TODO(JamePeng): verify the initial value diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp index 1843bdd9a..01b303330 100644 --- a/src/core/hle/service/apt/apt_s.cpp +++ b/src/core/hle/service/apt/apt_s.cpp @@ -62,8 +62,8 @@ APT_S::APT_S(std::shared_ptr apt) {0x00330000, &APT_S::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"}, {0x00340084, nullptr, "SendDeliverArg"}, {0x00350080, nullptr, "ReceiveDeliverArg"}, - {0x00360040, nullptr, "LoadSysMenuArg"}, - {0x00370042, nullptr, "StoreSysMenuArg"}, + {0x00360040, &APT_S::LoadSysMenuArg, "LoadSysMenuArg"}, + {0x00370042, &APT_S::StoreSysMenuArg, "StoreSysMenuArg"}, {0x00380040, nullptr, "PreloadResidentApplet"}, {0x00390040, nullptr, "PrepareToStartResidentApplet"}, {0x003A0044, nullptr, "StartResidentApplet"}, diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp index 0ecbd65da..ac354dc23 100644 --- a/src/core/hle/service/apt/apt_u.cpp +++ b/src/core/hle/service/apt/apt_u.cpp @@ -62,8 +62,8 @@ APT_U::APT_U(std::shared_ptr apt) {0x00330000, &APT_U::GetProgramIdOnApplicationJump, "GetProgramIdOnApplicationJump"}, {0x00340084, nullptr, "SendDeliverArg"}, {0x00350080, nullptr, "ReceiveDeliverArg"}, - {0x00360040, nullptr, "LoadSysMenuArg"}, - {0x00370042, nullptr, "StoreSysMenuArg"}, + {0x00360040, &APT_U::LoadSysMenuArg, "LoadSysMenuArg"}, + {0x00370042, &APT_U::StoreSysMenuArg, "StoreSysMenuArg"}, {0x00380040, nullptr, "PreloadResidentApplet"}, {0x00390040, nullptr, "PrepareToStartResidentApplet"}, {0x003A0044, nullptr, "StartResidentApplet"},