From 5682608df76b614cadff6061cff35dcf100b944b Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 13:01:21 -0500 Subject: [PATCH 1/6] Services/APT: Use boost::optional for the APT parameter structure. --- src/core/hle/service/apt/apt.cpp | 46 ++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index df4b5cc3f..e4068926a 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/common_paths.h" #include "common/file_util.h" #include "common/logging/log.h" @@ -44,7 +45,7 @@ static u8 unknown_ns_state_field; static ScreencapPostPermission screen_capture_post_permission; /// Parameter data to be returned in the next call to Glance/ReceiveParameter -static MessageParameter next_parameter; +static boost::optional next_parameter; void SendParameter(const MessageParameter& parameter) { next_parameter = parameter; @@ -227,18 +228,20 @@ void ReceiveParameter(Service::Interface* self) { buffer_size, static_buff_size); IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); + rb.Push(RESULT_SUCCESS); // No error - rb.Push(next_parameter.sender_id); - rb.Push(next_parameter.signal); // Signal type - ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); - rb.Push(static_cast(next_parameter.buffer.size())); // Parameter buffer size + rb.Push(next_parameter->sender_id); + rb.Push(next_parameter->signal); // Signal type + ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); + rb.Push(static_cast(next_parameter->buffer.size())); // Parameter buffer size - rb.PushMoveHandles((next_parameter.object != nullptr) - ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap() + rb.PushMoveHandles((next_parameter->object != nullptr) + ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() : 0); - rb.PushStaticBuffer(buffer, static_cast(next_parameter.buffer.size()), 0); - Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); + rb.PushStaticBuffer(buffer, static_cast(next_parameter->buffer.size()), 0); + + Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } @@ -258,17 +261,18 @@ void GlanceParameter(Service::Interface* self) { IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); rb.Push(RESULT_SUCCESS); // No error - rb.Push(next_parameter.sender_id); - rb.Push(next_parameter.signal); // Signal type - ASSERT_MSG(next_parameter.buffer.size() <= buffer_size, "Input static buffer is too small !"); - rb.Push(static_cast(next_parameter.buffer.size())); // Parameter buffer size + rb.Push(next_parameter->sender_id); + rb.Push(next_parameter->signal); // Signal type + ASSERT_MSG(next_parameter->buffer.size() <= buffer_size, "Input static buffer is too small !"); + rb.Push(static_cast(next_parameter->buffer.size())); // Parameter buffer size - rb.PushCopyHandles((next_parameter.object != nullptr) - ? Kernel::g_handle_table.Create(next_parameter.object).Unwrap() + rb.PushMoveHandles((next_parameter->object != nullptr) + ? Kernel::g_handle_table.Create(next_parameter->object).Unwrap() : 0); - rb.PushStaticBuffer(buffer, static_cast(next_parameter.buffer.size()), 0); - Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); + rb.PushStaticBuffer(buffer, static_cast(next_parameter->buffer.size()), 0); + + Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } @@ -800,8 +804,10 @@ void Init() { notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification"); parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start"); - next_parameter.signal = static_cast(SignalType::Wakeup); - next_parameter.destination_id = 0x300; + // Initialize the parameter to wake up the application. + next_parameter.emplace(); + next_parameter->signal = static_cast(SignalType::Wakeup); + next_parameter->destination_id = static_cast(AppletId::Application); } void Shutdown() { @@ -812,7 +818,7 @@ void Shutdown() { notification_event = nullptr; parameter_event = nullptr; - next_parameter.object = nullptr; + next_parameter = boost::none; HLE::Applets::Shutdown(); } From 2dc720c355dad55a607c1f993fc823cc198bed08 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 13:02:40 -0500 Subject: [PATCH 2/6] Services/APT: Use the right error codes in ReceiveParameter and GlanceParameter when the parameter doesn't exist. --- src/core/hle/service/apt/apt.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index e4068926a..b5748693f 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -227,6 +227,20 @@ void ReceiveParameter(Service::Interface* self) { "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); + if (!next_parameter) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status)); + return; + } + + if (next_parameter->destination_id != app_id) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, + ErrorLevel::Status)); + return; + } + IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); rb.Push(RESULT_SUCCESS); // No error @@ -259,6 +273,20 @@ void GlanceParameter(Service::Interface* self) { "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); + if (!next_parameter) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status)); + return; + } + + if (next_parameter->destination_id != app_id) { + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Applet, ErrorSummary::NotFound, + ErrorLevel::Status)); + return; + } + IPC::RequestBuilder rb = rp.MakeBuilder(4, 4); rb.Push(RESULT_SUCCESS); // No error rb.Push(next_parameter->sender_id); From e403638d9b2cbd7f7dbacd14c3c4bf9863bf7b34 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 13:03:28 -0500 Subject: [PATCH 3/6] Services/APT: Properly clear the apt parameter after a successful ReceiveParameter call. --- src/core/hle/service/apt/apt.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index b5748693f..b6c013d43 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -257,7 +257,9 @@ void ReceiveParameter(Service::Interface* self) { Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); - LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); + // Clear the parameter + next_parameter = boost::none; + LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void GlanceParameter(Service::Interface* self) { @@ -302,7 +304,11 @@ void GlanceParameter(Service::Interface* self) { Memory::WriteBlock(buffer, next_parameter->buffer.data(), next_parameter->buffer.size()); - LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); + // Note: The NS module always clears the DSPSleep and DSPWakeup signals even in GlanceParameter. + if (next_parameter->signal == static_cast(SignalType::DspSleep) || + next_parameter->signal == static_cast(SignalType::DspWakeup)) + next_parameter = boost::none; + LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void CancelParameter(Service::Interface* self) { From a9bc417f5948dc63f182d31e4ba271aa23efe84d Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 13:09:45 -0500 Subject: [PATCH 4/6] Services/APT: Reset the APT parameter inside CancelParameter if the conditions are met. --- src/core/hle/service/apt/apt.cpp | 33 ++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index b6c013d43..9cfb7f71e 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -314,17 +314,34 @@ void GlanceParameter(Service::Interface* self) { void CancelParameter(Service::Interface* self) { IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0xF, 4, 0); // 0xF0100 - u32 check_sender = rp.Pop(); + bool check_sender = rp.Pop(); u32 sender_appid = rp.Pop(); - u32 check_receiver = rp.Pop(); + bool check_receiver = rp.Pop(); u32 receiver_appid = rp.Pop(); - IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); - rb.Push(RESULT_SUCCESS); // No error - rb.Push(true); // Set to Success - LOG_WARNING(Service_APT, "(STUBBED) called check_sender=0x%08X, sender_appid=0x%08X, " - "check_receiver=0x%08X, receiver_appid=0x%08X", - check_sender, sender_appid, check_receiver, receiver_appid); + bool cancellation_success = true; + + if (!next_parameter) { + cancellation_success = false; + } else { + if (check_sender && next_parameter->sender_id != sender_appid) + cancellation_success = false; + + if (check_receiver && next_parameter->destination_id != receiver_appid) + cancellation_success = false; + } + + if (cancellation_success) + next_parameter = boost::none; + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + + rb.Push(RESULT_SUCCESS); // No error + rb.Push(cancellation_success); + + LOG_DEBUG(Service_APT, "called check_sender=%u, sender_appid=0x%08X, " + "check_receiver=%u, receiver_appid=0x%08X", + check_sender, sender_appid, check_receiver, receiver_appid); } void PrepareToStartApplication(Service::Interface* self) { From 68596a706860f37de876ca070f9de6e664df0d05 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 13:19:55 -0500 Subject: [PATCH 5/6] Services/APT: Return the proper error code when calling SendParameter with an outstanding parameter already in memory. --- src/core/hle/service/apt/apt.cpp | 15 +++++++++++---- src/core/hle/service/apt/apt.h | 6 ++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 9cfb7f71e..987fb0992 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -192,6 +192,13 @@ void SendParameter(Service::Interface* self) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + // A new parameter can not be sent if the previous one hasn't been consumed yet + if (next_parameter) { + rb.Push(ResultCode(ErrCodes::ParameterPresent, ErrorModule::Applet, + ErrorSummary::InvalidState, ErrorLevel::Status)); + return; + } + if (dest_applet == nullptr) { LOG_ERROR(Service_APT, "Unknown applet id=0x%08X", dst_app_id); rb.Push(-1); // TODO(Subv): Find the right error code @@ -208,10 +215,10 @@ void SendParameter(Service::Interface* self) { rb.Push(dest_applet->ReceiveParameter(param)); - LOG_WARNING(Service_APT, - "(STUBBED) called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," - "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", - src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); + LOG_DEBUG(Service_APT, + "called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," + "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", + src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); } void ReceiveParameter(Service::Interface* self) { diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index ee80926d2..106754853 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h @@ -116,6 +116,12 @@ enum class ScreencapPostPermission : u32 { DisableScreenshotPostingToMiiverse = 3 }; +namespace ErrCodes { +enum { + ParameterPresent = 2, +}; +} + /// Send a parameter to the currently-running application, which will read it via ReceiveParameter void SendParameter(const MessageParameter& parameter); From e59ab7c1d695e3eb303c5dd37cd0fde814657f53 Mon Sep 17 00:00:00 2001 From: Subv Date: Fri, 21 Jul 2017 15:03:06 -0500 Subject: [PATCH 6/6] Service/APT: Log Send/Cancel/Receive/GlanceParameter calls even if they return an error. --- src/core/hle/service/apt/apt.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index 987fb0992..aad23e900 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp @@ -190,6 +190,11 @@ void SendParameter(Service::Interface* self) { std::shared_ptr dest_applet = HLE::Applets::Applet::Get(static_cast(dst_app_id)); + LOG_DEBUG(Service_APT, + "called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," + "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", + src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); // A new parameter can not be sent if the previous one hasn't been consumed yet @@ -214,11 +219,6 @@ void SendParameter(Service::Interface* self) { Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); rb.Push(dest_applet->ReceiveParameter(param)); - - LOG_DEBUG(Service_APT, - "called src_app_id=0x%08X, dst_app_id=0x%08X, signal_type=0x%08X," - "buffer_size=0x%08X, handle=0x%08X, size=0x%08zX, in_param_buffer_ptr=0x%08X", - src_app_id, dst_app_id, signal_type, buffer_size, handle, size, buffer); } void ReceiveParameter(Service::Interface* self) { @@ -234,6 +234,8 @@ void ReceiveParameter(Service::Interface* self) { "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); + LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); + if (!next_parameter) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, @@ -266,7 +268,6 @@ void ReceiveParameter(Service::Interface* self) { // Clear the parameter next_parameter = boost::none; - LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void GlanceParameter(Service::Interface* self) { @@ -282,6 +283,8 @@ void GlanceParameter(Service::Interface* self) { "buffer_size is bigger than the size in the buffer descriptor (0x%08X > 0x%08zX)", buffer_size, static_buff_size); + LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); + if (!next_parameter) { IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(ResultCode(ErrorDescription::NoData, ErrorModule::Applet, @@ -315,7 +318,6 @@ void GlanceParameter(Service::Interface* self) { if (next_parameter->signal == static_cast(SignalType::DspSleep) || next_parameter->signal == static_cast(SignalType::DspWakeup)) next_parameter = boost::none; - LOG_DEBUG(Service_APT, "called app_id=0x%08X, buffer_size=0x%08zX", app_id, buffer_size); } void CancelParameter(Service::Interface* self) {