summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/svc
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/svc/svc_info.cpp5
-rw-r--r--src/core/hle/kernel/svc/svc_port.cpp51
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp45
-rw-r--r--src/core/hle/kernel/svc_types.h1
4 files changed, 54 insertions, 48 deletions
diff --git a/src/core/hle/kernel/svc/svc_info.cpp b/src/core/hle/kernel/svc/svc_info.cpp
index 58dc47508..cbed4dc8c 100644
--- a/src/core/hle/kernel/svc/svc_info.cpp
+++ b/src/core/hle/kernel/svc/svc_info.cpp
@@ -126,6 +126,11 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
*result = process->GetTotalPhysicalMemoryUsedWithoutSystemResource();
return ResultSuccess;
+ case InfoType::IsApplication:
+ LOG_WARNING(Kernel_SVC, "(STUBBED) Assuming process is application");
+ *result = true;
+ return ResultSuccess;
+
case InfoType::FreeThreadCount:
*result = process->GetFreeThreadCount();
return ResultSuccess;
diff --git a/src/core/hle/kernel/svc/svc_port.cpp b/src/core/hle/kernel/svc/svc_port.cpp
index 0b5b4ba2b..78c2a8d17 100644
--- a/src/core/hle/kernel/svc/svc_port.cpp
+++ b/src/core/hle/kernel/svc/svc_port.cpp
@@ -12,56 +12,40 @@
namespace Kernel::Svc {
-/// Connect to an OS service given the port name, returns the handle to the port to out
-Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address) {
- auto& memory = system.Memory();
- if (!memory.IsValidVirtualAddress(port_name_address)) {
- LOG_ERROR(Kernel_SVC,
- "Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
- port_name_address);
- return ResultNotFound;
- }
+Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr user_name) {
+ // Copy the provided name from user memory to kernel memory.
+ auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
- static constexpr std::size_t PortNameMaxLength = 11;
- // Read 1 char beyond the max allowed port name to detect names that are too long.
- const std::string port_name = memory.ReadCString(port_name_address, PortNameMaxLength + 1);
- if (port_name.size() > PortNameMaxLength) {
- LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
- port_name.size());
- return ResultOutOfRange;
- }
+ std::array<char, KObjectName::NameLengthMax> name{};
+ std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
- LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
+ // Validate that the name is valid.
+ R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
// Get the current handle table.
- auto& kernel = system.Kernel();
- auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
+ auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Find the client port.
- auto port = kernel.CreateNamedServicePort(port_name);
- if (!port) {
- LOG_ERROR(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
- return ResultNotFound;
- }
+ auto port = KObjectName::Find<KClientPort>(system.Kernel(), name.data());
+ R_UNLESS(port.IsNotNull(), ResultNotFound);
// Reserve a handle for the port.
// NOTE: Nintendo really does write directly to the output handle here.
R_TRY(handle_table.Reserve(out));
- auto handle_guard = SCOPE_GUARD({ handle_table.Unreserve(*out); });
+ ON_RESULT_FAILURE {
+ handle_table.Unreserve(*out);
+ };
// Create a session.
- KClientSession* session{};
+ KClientSession* session;
R_TRY(port->CreateSession(std::addressof(session)));
- kernel.RegisterNamedServiceHandler(port_name, &port->GetParent()->GetServerPort());
-
// Register the session in the table, close the extra reference.
handle_table.Register(*out, session);
session->Close();
// We succeeded.
- handle_guard.Cancel();
- return ResultSuccess;
+ R_SUCCEED();
}
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
@@ -78,8 +62,11 @@ Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
int32_t max_sessions) {
// Copy the provided name from user memory to kernel memory.
+ auto string_name = system.Memory().ReadCString(user_name, KObjectName::NameLengthMax);
+
+ // Copy the provided name from user memory to kernel memory.
std::array<char, KObjectName::NameLengthMax> name{};
- system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
+ std::strncpy(name.data(), string_name.c_str(), KObjectName::NameLengthMax - 1);
// Validate that sessions and name are valid.
R_UNLESS(max_sessions >= 0, ResultOutOfRange);
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 1a8f7e191..9e7bf9530 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
-/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
- s64 nano_seconds) {
- LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}",
- handles_address, num_handles, nano_seconds);
-
+static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
+ int32_t num_handles, int64_t timeout_ns) {
// Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+ // Get the synchronization context.
auto& kernel = system.Kernel();
+ auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
std::vector<KSynchronizationObject*> objs(num_handles);
- const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
if (num_handles > 0) {
@@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
num_handles),
ResultInvalidHandle);
- for (const auto& obj : objs) {
- kernel.RegisterInUseObject(obj);
- }
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
- for (s32 i = 0; i < num_handles; ++i) {
- kernel.UnregisterInUseObject(objs[i]);
+ for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
- return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()),
- nano_seconds);
+ // Wait on the objects.
+ Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(),
+ static_cast<s32>(objs.size()), timeout_ns);
+
+ R_SUCCEED_IF(res == ResultSessionClosed);
+ R_RETURN(res);
+}
+
+/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
+Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles,
+ int32_t num_handles, int64_t timeout_ns) {
+ LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
+ num_handles, timeout_ns);
+
+ // Ensure number of handles is valid.
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+
+ std::vector<Handle> handles(num_handles);
+ if (num_handles > 0) {
+ system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
+ }
+
+ R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
}
/// Resumes a thread waiting on WaitSynchronization
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 542c13461..39355d9c4 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -151,6 +151,7 @@ enum class InfoType : u32 {
FreeThreadCount = 24,
ThreadTickCount = 25,
IsSvcPermitted = 26,
+ IoRegionHint = 27,
MesosphereMeta = 65000,
MesosphereCurrentProcess = 65001,