From 1e0e36c2c238c8b3c81c2672872459ed111265aa Mon Sep 17 00:00:00 2001 From: FearlessTobi Date: Thu, 22 Feb 2024 16:29:22 +0100 Subject: [PATCH] svc: Implement GetSystemInfo Needed for fssrv_program_info. --- src/core/hle/kernel/svc.h | 1 + src/core/hle/kernel/svc/svc_info.cpp | 85 ++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/core/hle/kernel/svc.h b/src/core/hle/kernel/svc.h index 828f396113..deac1a57bb 100644 --- a/src/core/hle/kernel/svc.h +++ b/src/core/hle/kernel/svc.h @@ -57,6 +57,7 @@ Result GetThreadId(Core::System& system, uint64_t* out_thread_id, Handle thread_ void Break(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size); Result OutputDebugString(Core::System& system, uint64_t debug_str, uint64_t len); void ReturnFromException(Core::System& system, Result result); +Result GetInitialProcessIdRange(u64 *out, InitialProcessIdRangeInfo info); Result GetInfo(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype); void FlushEntireDataCache(Core::System& system); Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size); diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp index 231e4d0e1b..5d6734620b 100644 --- a/src/core/hle/kernel/svc/svc_info.cpp +++ b/src/core/hle/kernel/svc/svc_info.cpp @@ -1,14 +1,33 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include "common/assert.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/hle/api_version.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_resource_limit.h" #include "core/hle/kernel/svc.h" namespace Kernel::Svc { +Result GetInitialProcessIdRange(u64* out, InitialProcessIdRangeInfo info) { + switch (info) { + case InitialProcessIdRangeInfo::Minimum: + static_assert(KProcess::InitialProcessIdMin <= KProcess::InitialProcessIdMax); + *out = KProcess::InitialProcessIdMin; + break; + case InitialProcessIdRangeInfo::Maximum: + static_assert(KProcess::InitialProcessIdMin <= KProcess::InitialProcessIdMax); + *out = KProcess::InitialProcessIdMax; + break; + default: + R_THROW(ResultInvalidCombination); + } + + R_SUCCEED(); +} + /// Gets system/memory information for the current process Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle, u64 info_sub_id) { @@ -174,9 +193,17 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle R_SUCCEED(); case InfoType::InitialProcessIdRange: - LOG_WARNING(Kernel_SVC, - "(STUBBED) Attempted to query privileged process id bounds, returned 0"); - *result = 0; + // NOTE: This info type was added in 4.0.0, and removed in 5.0.0 + R_UNLESS(HLE::ApiVersion::GetTargetFirmware() < + HLE::ApiVersion::AtmosphereTargetFirmware(5, 0, 0), + ResultInvalidEnumValue); + + // Verify the input handle is invalid + R_UNLESS(handle == InvalidHandle, ResultInvalidHandle); + + // Get the process id range + R_TRY( + GetInitialProcessIdRange(result, static_cast(info_sub_id))); R_SUCCEED(); case InfoType::ThreadTickCount: { @@ -255,10 +282,58 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle } } +static constexpr bool IsValidMemoryPool(u64 pool) { + switch (static_cast(pool)) { + case KMemoryManager::Pool::Application: + case KMemoryManager::Pool::Applet: + case KMemoryManager::Pool::System: + case KMemoryManager::Pool::SystemNonSecure: + return true; + default: + return false; + } +} + Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype) { - UNIMPLEMENTED(); - R_THROW(ResultNotImplemented); + switch (info_type) { + case SystemInfoType::TotalPhysicalMemorySize: + case SystemInfoType::UsedPhysicalMemorySize: { + // Verify the input handle is invalid + R_UNLESS(handle == InvalidHandle, ResultInvalidHandle); + + // Verify the sub-type is valid + R_UNLESS(IsValidMemoryPool(info_subtype), ResultInvalidCombination); + + // Convert to pool + const auto pool = static_cast(info_subtype); + + // Get the memory size + auto& mm = system.Kernel().MemoryManager(); + switch (info_type) { + case SystemInfoType::TotalPhysicalMemorySize: + *out = mm.GetSize(pool); + break; + case SystemInfoType::UsedPhysicalMemorySize: + *out = mm.GetSize(pool) - mm.GetFreeSize(pool); + break; + default: + UNREACHABLE(); + break; + } + } break; + case SystemInfoType::InitialProcessIdRange: { + // Verify the handle is invalid + R_UNLESS(handle == InvalidHandle, ResultInvalidHandle); + + // Get the process id range + R_TRY(GetInitialProcessIdRange(out, static_cast(info_subtype))); + } break; + default: + R_THROW(ResultInvalidEnumValue); + } + + R_SUCCEED(); } Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,