diff --git a/libraries/libmesosphere/include/mesosphere/kern_debug_log.hpp b/libraries/libmesosphere/include/mesosphere/kern_debug_log.hpp index 94aaabf66..0e7f319b7 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_debug_log.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_debug_log.hpp @@ -15,6 +15,7 @@ */ #pragma once #include +#include namespace ams::kern { @@ -26,6 +27,8 @@ namespace ams::kern { static NOINLINE void Printf(const char *format, ...) __attribute__((format(printf, 1, 2))); static NOINLINE void VPrintf(const char *format, ::std::va_list vl); + + static NOINLINE Result PrintUserString(ams::kern::svc::KUserPointer user_str, size_t len); }; } diff --git a/libraries/libmesosphere/source/kern_debug_log.cpp b/libraries/libmesosphere/source/kern_debug_log.cpp index 45a53f534..bf06f82d2 100644 --- a/libraries/libmesosphere/source/kern_debug_log.cpp +++ b/libraries/libmesosphere/source/kern_debug_log.cpp @@ -404,18 +404,52 @@ namespace ams::kern { char g_print_buffer[0x400]; void PutString(const char *str) { - if (g_initialized_impl) { - while (*str) { - const char c = *(str++); - if (c == '\n') { - KDebugLogImpl::PutChar('\r'); - } - KDebugLogImpl::PutChar(c); - } - KDebugLogImpl::Flush(); + /* Only print if the implementation is initialized. */ + if (!g_initialized_impl) { + return; } + + while (*str) { + /* Get a character. */ + const char c = *(str++); + + /* Print the character. */ + if (c == '\n') { + KDebugLogImpl::PutChar('\r'); + } + KDebugLogImpl::PutChar(c); + } + + KDebugLogImpl::Flush(); } + #if defined(MESOSPHERE_ENABLE_DEBUG_PRINT) + + Result PutUserString(ams::kern::svc::KUserPointer user_str, size_t len) { + /* Only print if the implementation is initialized. */ + if (!g_initialized_impl) { + return ResultSuccess(); + } + + for (size_t i = 0; i < len; ++i) { + /* Get a character. */ + char c; + R_TRY(user_str.CopyArrayElementTo(std::addressof(c), i)); + + /* Print the character. */ + if (c == '\n') { + KDebugLogImpl::PutChar('\r'); + } + KDebugLogImpl::PutChar(c); + } + + KDebugLogImpl::Flush(); + + return ResultSuccess(); + } + + #endif + } @@ -455,4 +489,18 @@ namespace ams::kern { VSNPrintfImpl(dst, dst_size, format, vl); } + Result KDebugLog::PrintUserString(ams::kern::svc::KUserPointer user_str, size_t len) { + /* If printing is enabled, print the user string. */ + #if defined(MESOSPHERE_ENABLE_DEBUG_PRINT) + if (KTargetSystem::IsDebugLoggingEnabled()) { + KScopedInterruptDisable di; + KScopedSpinLock lk(g_debug_log_lock); + + R_TRY(PutUserString(user_str, len)); + } + #endif + + return ResultSuccess(); + } + } diff --git a/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp b/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp index 547ae5f14..f337c4e5d 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_debug_string.cpp @@ -21,20 +21,29 @@ namespace ams::kern::svc { namespace { + Result OutputDebugString(KUserPointer debug_str, size_t len) { + /* Succeed immediately if there's nothing to output. */ + R_SUCCEED_IF(len == 0); + /* Ensure that the data being output is in range. */ + R_UNLESS(GetCurrentProcess().GetPageTable().Contains(KProcessAddress(debug_str.GetUnsafePointer()), len), svc::ResultInvalidCurrentMemory()); + + /* Output the string. */ + return KDebugLog::PrintUserString(debug_str, len); + } } /* ============================= 64 ABI ============================= */ Result OutputDebugString64(KUserPointer debug_str, ams::svc::Size len) { - MESOSPHERE_PANIC("Stubbed SvcOutputDebugString64 was called."); + return OutputDebugString(debug_str, len); } /* ============================= 64From32 ABI ============================= */ Result OutputDebugString64From32(KUserPointer debug_str, ams::svc::Size len) { - MESOSPHERE_PANIC("Stubbed SvcOutputDebugString64From32 was called."); + return OutputDebugString(debug_str, len); } } diff --git a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp index 5c25342ee..8e920b799 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp @@ -21,7 +21,25 @@ namespace ams::kern::svc { namespace { + Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) { + /* Get the thread from its handle. */ + KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle()); + /* Get the thread's priority. */ + *out_priority = thread->GetPriority(); + return ResultSuccess(); + } + + Result GetThreadId(uint64_t *out_thread_id, ams::svc::Handle thread_handle) { + /* Get the thread from its handle. */ + KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject(thread_handle); + R_UNLESS(thread.IsNotNull(), svc::ResultInvalidHandle()); + + /* Get the thread's id. */ + *out_thread_id = thread->GetId(); + return ResultSuccess(); + } } @@ -44,7 +62,7 @@ namespace ams::kern::svc { } Result GetThreadPriority64(int32_t *out_priority, ams::svc::Handle thread_handle) { - MESOSPHERE_PANIC("Stubbed SvcGetThreadPriority64 was called."); + return GetThreadPriority(out_priority, thread_handle); } Result SetThreadPriority64(ams::svc::Handle thread_handle, int32_t priority) { @@ -60,7 +78,7 @@ namespace ams::kern::svc { } Result GetThreadId64(uint64_t *out_thread_id, ams::svc::Handle thread_handle) { - MESOSPHERE_PANIC("Stubbed SvcGetThreadId64 was called."); + return GetThreadId(out_thread_id, thread_handle); } Result GetDebugFutureThreadInfo64(ams::svc::lp64::LastThreadContext *out_context, uint64_t *thread_id, ams::svc::Handle debug_handle, int64_t ns) { @@ -98,7 +116,7 @@ namespace ams::kern::svc { } Result GetThreadPriority64From32(int32_t *out_priority, ams::svc::Handle thread_handle) { - MESOSPHERE_PANIC("Stubbed SvcGetThreadPriority64From32 was called."); + return GetThreadPriority(out_priority, thread_handle); } Result SetThreadPriority64From32(ams::svc::Handle thread_handle, int32_t priority) { @@ -114,7 +132,7 @@ namespace ams::kern::svc { } Result GetThreadId64From32(uint64_t *out_thread_id, ams::svc::Handle thread_handle) { - MESOSPHERE_PANIC("Stubbed SvcGetThreadId64From32 was called."); + return GetThreadId(out_thread_id, thread_handle); } Result GetDebugFutureThreadInfo64From32(ams::svc::ilp32::LastThreadContext *out_context, uint64_t *thread_id, ams::svc::Handle debug_handle, int64_t ns) {