diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/mutex.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 89 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 55 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 64 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 15 | ||||
| -rw-r--r-- | src/core/hle/service/acc/acc.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/service/am/am.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audout_u.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 19 | ||||
| -rw-r--r-- | src/core/hle/service/nim/nim.cpp | 102 | ||||
| -rw-r--r-- | src/core/hle/service/sm/sm.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/ssl/ssl.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 30 |
18 files changed, 312 insertions, 153 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 7545ecf2a..a4bfe2eb0 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -290,13 +290,6 @@ public: Skip(CommandIdSize, false); } - ResponseBuilder MakeBuilder(u32 normal_params_size, u32 num_handles_to_copy, - u32 num_handles_to_move, - ResponseBuilder::Flags flags = ResponseBuilder::Flags::None) const { - return ResponseBuilder{*context, normal_params_size, num_handles_to_copy, - num_handles_to_move, flags}; - } - template <typename T> T Pop(); diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index 51f4544be..81675eac5 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -16,6 +16,7 @@ #include "core/hle/kernel/object.h" #include "core/hle/kernel/thread.h" #include "core/hle/result.h" +#include "core/memory.h" namespace Kernel { diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 7a272d031..121f741fd 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -7,10 +7,12 @@ #include "common/assert.h" #include "common/common_funcs.h" #include "common/logging/log.h" +#include "core/core.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" +#include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/hle/kernel/vm_manager.h" #include "core/memory.h" @@ -125,7 +127,92 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { vm_manager.LogLayout(); status = ProcessStatus::Running; - Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, this); + Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, *this); +} + +void Process::PrepareForTermination() { + status = ProcessStatus::Exited; + + const auto stop_threads = [this](const std::vector<SharedPtr<Thread>>& thread_list) { + for (auto& thread : thread_list) { + if (thread->owner_process != this) + continue; + + if (thread == GetCurrentThread()) + continue; + + // TODO(Subv): When are the other running/ready threads terminated? + ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny || + thread->status == ThreadStatus::WaitSynchAll, + "Exiting processes with non-waiting threads is currently unimplemented"); + + thread->Stop(); + } + }; + + auto& system = Core::System::GetInstance(); + stop_threads(system.Scheduler(0)->GetThreadList()); + stop_threads(system.Scheduler(1)->GetThreadList()); + stop_threads(system.Scheduler(2)->GetThreadList()); + stop_threads(system.Scheduler(3)->GetThreadList()); +} + +/** + * Finds a free location for the TLS section of a thread. + * @param tls_slots The TLS page array of the thread's owner process. + * Returns a tuple of (page, slot, alloc_needed) where: + * page: The index of the first allocated TLS page that has free slots. + * slot: The index of the first free slot in the indicated page. + * alloc_needed: Whether there's a need to allocate a new TLS page (All pages are full). + */ +static std::tuple<std::size_t, std::size_t, bool> FindFreeThreadLocalSlot( + const std::vector<std::bitset<8>>& tls_slots) { + // Iterate over all the allocated pages, and try to find one where not all slots are used. + for (std::size_t page = 0; page < tls_slots.size(); ++page) { + const auto& page_tls_slots = tls_slots[page]; + if (!page_tls_slots.all()) { + // We found a page with at least one free slot, find which slot it is + for (std::size_t slot = 0; slot < page_tls_slots.size(); ++slot) { + if (!page_tls_slots.test(slot)) { + return std::make_tuple(page, slot, false); + } + } + } + } + + return std::make_tuple(0, 0, true); +} + +VAddr Process::MarkNextAvailableTLSSlotAsUsed(Thread& thread) { + auto [available_page, available_slot, needs_allocation] = FindFreeThreadLocalSlot(tls_slots); + + if (needs_allocation) { + tls_slots.emplace_back(0); // The page is completely available at the start + available_page = tls_slots.size() - 1; + available_slot = 0; // Use the first slot in the new page + + // Allocate some memory from the end of the linear heap for this region. + auto& tls_memory = thread.GetTLSMemory(); + tls_memory->insert(tls_memory->end(), Memory::PAGE_SIZE, 0); + + vm_manager.RefreshMemoryBlockMappings(tls_memory.get()); + + vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, + tls_memory, 0, Memory::PAGE_SIZE, MemoryState::ThreadLocal); + } + + tls_slots[available_page].set(available_slot); + + return Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + + available_slot * Memory::TLS_ENTRY_SIZE; +} + +void Process::FreeTLSSlot(VAddr tls_address) { + const VAddr tls_base = tls_address - Memory::TLS_AREA_VADDR; + const VAddr tls_page = tls_base / Memory::PAGE_SIZE; + const VAddr tls_slot = (tls_base % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; + + tls_slots[tls_page].reset(tls_slot); } void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 81538f70c..04d74e572 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -131,6 +131,16 @@ public: return HANDLE_TYPE; } + /// Gets the current status of the process + ProcessStatus GetStatus() const { + return status; + } + + /// Gets the unique ID that identifies this particular process. + u32 GetProcessID() const { + return process_id; + } + /// Title ID corresponding to the process u64 program_id; @@ -154,11 +164,6 @@ public: u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK; u32 allowed_thread_priority_mask = 0xFFFFFFFF; u32 is_virtual_address_memory_enabled = 0; - /// Current status of the process - ProcessStatus status; - - /// The ID of this process - u32 process_id = 0; /** * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them @@ -171,13 +176,42 @@ public: */ void Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size); + /** + * Prepares a process for termination by stopping all of its threads + * and clearing any other resources. + */ + void PrepareForTermination(); + void LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr); /////////////////////////////////////////////////////////////////////////////////////////////// // Memory Management + // Marks the next available region as used and returns the address of the slot. + VAddr MarkNextAvailableTLSSlotAsUsed(Thread& thread); + + // Frees a used TLS slot identified by the given address + void FreeTLSSlot(VAddr tls_address); + + ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); + ResultCode HeapFree(VAddr target, u32 size); + + ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size); + + ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); + VMManager vm_manager; +private: + explicit Process(KernelCore& kernel); + ~Process() override; + + /// Current status of the process + ProcessStatus status; + + /// The ID of this process + u32 process_id = 0; + // Memory used to back the allocations in the regular heap. A single vector is used to cover // the entire virtual address space extents that bound the allocations, including any holes. // This makes deallocation and reallocation of holes fast and keeps process memory contiguous @@ -197,17 +231,6 @@ public: std::vector<std::bitset<8>> tls_slots; std::string name; - - ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); - ResultCode HeapFree(VAddr target, u32 size); - - ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size); - - ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); - -private: - explicit Process(KernelCore& kernel); - ~Process() override; }; } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 371fc439e..0bc407098 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -169,7 +169,7 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) { return ERR_INVALID_HANDLE; } - *process_id = process->process_id; + *process_id = process->GetProcessID(); return RESULT_SUCCESS; } @@ -530,35 +530,13 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, VAdd /// Exits the current process static void ExitProcess() { - LOG_INFO(Kernel_SVC, "Process {} exiting", Core::CurrentProcess()->process_id); + auto& current_process = Core::CurrentProcess(); - ASSERT_MSG(Core::CurrentProcess()->status == ProcessStatus::Running, + LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID()); + ASSERT_MSG(current_process->GetStatus() == ProcessStatus::Running, "Process has already exited"); - Core::CurrentProcess()->status = ProcessStatus::Exited; - - auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) { - for (auto& thread : thread_list) { - if (thread->owner_process != Core::CurrentProcess()) - continue; - - if (thread == GetCurrentThread()) - continue; - - // TODO(Subv): When are the other running/ready threads terminated? - ASSERT_MSG(thread->status == ThreadStatus::WaitSynchAny || - thread->status == ThreadStatus::WaitSynchAll, - "Exiting processes with non-waiting threads is currently unimplemented"); - - thread->Stop(); - } - }; - - auto& system = Core::System::GetInstance(); - stop_threads(system.Scheduler(0)->GetThreadList()); - stop_threads(system.Scheduler(1)->GetThreadList()); - stop_threads(system.Scheduler(2)->GetThreadList()); - stop_threads(system.Scheduler(3)->GetThreadList()); + current_process->PrepareForTermination(); // Kill the current thread GetCurrentThread()->Stop(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index d4183d6e3..315f65338 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -65,10 +65,7 @@ void Thread::Stop() { wait_objects.clear(); // Mark the TLS slot in the thread's page as free. - const u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; - const u64 tls_slot = - ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; - Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot); + owner_process->FreeTLSSlot(tls_address); } void WaitCurrentThread_Sleep() { @@ -178,32 +175,6 @@ void Thread::ResumeFromWait() { } /** - * Finds a free location for the TLS section of a thread. - * @param tls_slots The TLS page array of the thread's owner process. - * Returns a tuple of (page, slot, alloc_needed) where: - * page: The index of the first allocated TLS page that has free slots. - * slot: The index of the first free slot in the indicated page. - * alloc_needed: Whether there's a need to allocate a new TLS page (All pages are full). - */ -static std::tuple<std::size_t, std::size_t, bool> GetFreeThreadLocalSlot( - const std::vector<std::bitset<8>>& tls_slots) { - // Iterate over all the allocated pages, and try to find one where not all slots are used. - for (std::size_t page = 0; page < tls_slots.size(); ++page) { - const auto& page_tls_slots = tls_slots[page]; - if (!page_tls_slots.all()) { - // We found a page with at least one free slot, find which slot it is - for (std::size_t slot = 0; slot < page_tls_slots.size(); ++slot) { - if (!page_tls_slots.test(slot)) { - return std::make_tuple(page, slot, false); - } - } - } - } - - return std::make_tuple(0, 0, true); -} - -/** * Resets a thread context, making it ready to be scheduled and run by the CPU * @param context Thread context to reset * @param stack_top Address of the top of the stack @@ -264,32 +235,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name thread->owner_process = owner_process; thread->scheduler = Core::System::GetInstance().Scheduler(processor_id); thread->scheduler->AddThread(thread, priority); - - // Find the next available TLS index, and mark it as used - auto& tls_slots = owner_process->tls_slots; - - auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots); - if (needs_allocation) { - tls_slots.emplace_back(0); // The page is completely available at the start - available_page = tls_slots.size() - 1; - available_slot = 0; // Use the first slot in the new page - - // Allocate some memory from the end of the linear heap for this region. - const std::size_t offset = thread->tls_memory->size(); - thread->tls_memory->insert(thread->tls_memory->end(), Memory::PAGE_SIZE, 0); - - auto& vm_manager = owner_process->vm_manager; - vm_manager.RefreshMemoryBlockMappings(thread->tls_memory.get()); - - vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE, - thread->tls_memory, 0, Memory::PAGE_SIZE, - MemoryState::ThreadLocal); - } - - // Mark the slot as used - tls_slots[available_page].set(available_slot); - thread->tls_address = Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE + - available_slot * Memory::TLS_ENTRY_SIZE; + thread->tls_address = thread->owner_process->MarkNextAvailableTLSSlotAsUsed(*thread); // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used // to initialize the context @@ -311,13 +257,13 @@ void Thread::BoostPriority(u32 priority) { } SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority, - SharedPtr<Process> owner_process) { + Process& owner_process) { // Setup page table so we can write to memory - SetCurrentPageTable(&Core::CurrentProcess()->vm_manager.page_table); + SetCurrentPageTable(&owner_process.vm_manager.page_table); // Initialize new "main" thread auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0, - Memory::STACK_AREA_VADDR_END, std::move(owner_process)); + Memory::STACK_AREA_VADDR_END, &owner_process); SharedPtr<Thread> thread = std::move(thread_res).Unwrap(); diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index df4748942..4250144c3 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -62,6 +62,9 @@ enum class ThreadWakeupReason { class Thread final : public WaitObject { public: + using TLSMemory = std::vector<u8>; + using TLSMemoryPtr = std::shared_ptr<TLSMemory>; + /** * Creates and returns a new thread. The new thread is immediately scheduled * @param kernel The kernel instance this thread will be created under. @@ -134,6 +137,14 @@ public: return thread_id; } + TLSMemoryPtr& GetTLSMemory() { + return tls_memory; + } + + const TLSMemoryPtr& GetTLSMemory() const { + return tls_memory; + } + /** * Resumes a thread from waiting */ @@ -269,7 +280,7 @@ private: explicit Thread(KernelCore& kernel); ~Thread() override; - std::shared_ptr<std::vector<u8>> tls_memory = std::make_shared<std::vector<u8>>(); + TLSMemoryPtr tls_memory = std::make_shared<TLSMemory>(); }; /** @@ -281,7 +292,7 @@ private: * @return A shared pointer to the main thread */ SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority, - SharedPtr<Process> owner_process); + Process& owner_process); /** * Gets the current thread diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 4d4eb542e..e61748ca3 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -130,11 +130,10 @@ private: void GetAccountId(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); - // TODO(Subv): Find out what this actually does and implement it. Stub it as an error for - // now since we do not implement NNID. Returning a bogus id here will cause games to send - // invalid IPC requests after ListOpenUsers is called. - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultCode(-1)); + // Should return a nintendo account ID + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u64>(1); } }; diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9c975325a..69bfce1c1 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -462,7 +462,7 @@ private: std::memcpy(&buffer[offset], data.data(), data.size()); - IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_AM, "called, offset={}", offset); @@ -478,7 +478,7 @@ private: ctx.WriteBuffer(buffer.data() + offset, size); - IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_AM, "called, offset={}", offset); @@ -568,7 +568,7 @@ private: IPC::RequestParser rp{ctx}; storage_stack.push(rp.PopIpcInterface<AM::IStorage>()); - IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 0)}; + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_DEBUG(Service_AM, "called"); @@ -616,7 +616,7 @@ void ILibraryAppletCreator::CreateStorage(Kernel::HLERequestContext& ctx) { const u64 size{rp.Pop<u64>()}; std::vector<u8> buffer(size); - IPC::ResponseBuilder rb{rp.MakeBuilder(2, 0, 1)}; + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<AM::IStorage>(std::move(buffer)); diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index 80a002322..ff1edefbb 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -190,7 +190,7 @@ void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) { ctx.WriteBuffer(DefaultDevice); - IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); rb.Push<u32>(1); // Amount of audio devices diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index e84c4fa2b..80ed4b152 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -25,7 +25,7 @@ public: {0, &IAudioRenderer::GetAudioRendererSampleRate, "GetAudioRendererSampleRate"}, {1, &IAudioRenderer::GetAudioRendererSampleCount, "GetAudioRendererSampleCount"}, {2, &IAudioRenderer::GetAudioRendererMixBufferCount, "GetAudioRendererMixBufferCount"}, - {3, nullptr, "GetAudioRendererState"}, + {3, &IAudioRenderer::GetAudioRendererState, "GetAudioRendererState"}, {4, &IAudioRenderer::RequestUpdateAudioRenderer, "RequestUpdateAudioRenderer"}, {5, &IAudioRenderer::StartAudioRenderer, "StartAudioRenderer"}, {6, &IAudioRenderer::StopAudioRenderer, "StopAudioRenderer"}, @@ -62,6 +62,13 @@ private: LOG_DEBUG(Service_Audio, "called"); } + void GetAudioRendererState(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(renderer->GetState()); + LOG_DEBUG(Service_Audio, "called"); + } + void GetAudioRendererMixBufferCount(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); @@ -137,7 +144,7 @@ private: constexpr std::array<char, 15> audio_interface{{"AudioInterface"}}; ctx.WriteBuffer(audio_interface); - IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); rb.Push<u32>(1); } @@ -151,7 +158,7 @@ private: auto file_buffer = ctx.ReadBuffer(); auto end = std::find(file_buffer.begin(), file_buffer.end(), '\0'); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -162,7 +169,7 @@ private: constexpr std::array<char, 12> audio_interface{{"AudioDevice"}}; ctx.WriteBuffer(audio_interface); - IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0); + IPC::ResponseBuilder rb{ctx, 3}; rb.Push(RESULT_SUCCESS); rb.Push<u32>(1); } diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 5c4971724..d349ee686 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -197,7 +197,7 @@ ResultVal<FileSys::VirtualDir> VfsDirectoryServiceWrapper::OpenDirectory(const s auto dir = GetDirectoryRelativeWrapped(backing, path); if (dir == nullptr) { // TODO(DarkLordZach): Find a better error code for this - return ResultCode(-1); + return FileSys::ERROR_PATH_NOT_FOUND; } return MakeResult(dir); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 256c49bfc..7c6b0a4e6 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -338,7 +338,7 @@ public: {106, &Hid::AcquireNpadStyleSetUpdateEventHandle, "AcquireNpadStyleSetUpdateEventHandle"}, {107, &Hid::DisconnectNpad, "DisconnectNpad"}, {108, &Hid::GetPlayerLedPattern, "GetPlayerLedPattern"}, - {109, nullptr, "ActivateNpadWithRevision"}, + {109, &Hid::ActivateNpadWithRevision, "ActivateNpadWithRevision"}, {120, &Hid::SetNpadJoyHoldType, "SetNpadJoyHoldType"}, {121, &Hid::GetNpadJoyHoldType, "GetNpadJoyHoldType"}, {122, &Hid::SetNpadJoyAssignmentModeSingleByDefault, "SetNpadJoyAssignmentModeSingleByDefault"}, @@ -603,6 +603,12 @@ private: rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_HID, "(STUBBED) called"); } + + void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_HID, "(STUBBED) called"); + } }; class HidDbg final : public ServiceFramework<HidDbg> { diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index ed4f5f539..10611ed6a 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -31,7 +31,7 @@ public: {1, &IRequest::GetResult, "GetResult"}, {2, &IRequest::GetSystemEventReadableHandles, "GetSystemEventReadableHandles"}, {3, &IRequest::Cancel, "Cancel"}, - {4, nullptr, "Submit"}, + {4, &IRequest::Submit, "Submit"}, {5, nullptr, "SetRequirement"}, {6, nullptr, "SetRequirementPreset"}, {8, nullptr, "SetPriority"}, @@ -61,6 +61,12 @@ public: } private: + void Submit(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + void GetRequestState(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 3}; @@ -114,10 +120,11 @@ public: private: void GetClientId(Kernel::HLERequestContext& ctx) { + static constexpr u32 client_id = 1; LOG_WARNING(Service_NIFM, "(STUBBED) called"); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); - rb.Push<u64>(0); + rb.Push<u64>(client_id); // Client ID needs to be non zero otherwise it's considered invalid } void CreateScanRequest(Kernel::HLERequestContext& ctx) { IPC::ResponseBuilder rb{ctx, 2, 0, 1}; @@ -141,10 +148,16 @@ private: rb.Push(RESULT_SUCCESS); } void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { - IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + ASSERT_MSG(ctx.GetReadBufferSize() == 0x17c, "NetworkProfileData is not the correct size"); + u128 uuid{}; + auto buffer = ctx.ReadBuffer(); + std::memcpy(&uuid, buffer.data() + 8, sizeof(u128)); + + IPC::ResponseBuilder rb{ctx, 6, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface<INetworkProfile>(); + rb.PushRaw<u128>(uuid); LOG_DEBUG(Service_NIFM, "called"); } diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp index bd05b0a70..c1737defa 100644 --- a/src/core/hle/service/nim/nim.cpp +++ b/src/core/hle/service/nim/nim.cpp @@ -2,6 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <chrono> +#include <ctime> +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/event.h" #include "core/hle/service/nim/nim.h" #include "core/hle/service/service.h" #include "core/hle/service/sm/sm.h" @@ -100,19 +104,111 @@ public: } }; +class IEnsureNetworkClockAvailabilityService final + : public ServiceFramework<IEnsureNetworkClockAvailabilityService> { +public: + IEnsureNetworkClockAvailabilityService() + : ServiceFramework("IEnsureNetworkClockAvailabilityService") { + static const FunctionInfo functions[] = { + {0, &IEnsureNetworkClockAvailabilityService::StartTask, "StartTask"}, + {1, &IEnsureNetworkClockAvailabilityService::GetFinishNotificationEvent, + "GetFinishNotificationEvent"}, + {2, &IEnsureNetworkClockAvailabilityService::GetResult, "GetResult"}, + {3, &IEnsureNetworkClockAvailabilityService::Cancel, "Cancel"}, + {4, &IEnsureNetworkClockAvailabilityService::IsProcessing, "IsProcessing"}, + {5, &IEnsureNetworkClockAvailabilityService::GetServerTime, "GetServerTime"}, + }; + RegisterHandlers(functions); + + auto& kernel = Core::System::GetInstance().Kernel(); + finished_event = + Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, + "IEnsureNetworkClockAvailabilityService:FinishEvent"); + } + +private: + Kernel::SharedPtr<Kernel::Event> finished_event; + + void StartTask(Kernel::HLERequestContext& ctx) { + // No need to connect to the internet, just finish the task straight away. + finished_event->Signal(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_NIM, "called"); + } + + void GetFinishNotificationEvent(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(finished_event); + LOG_DEBUG(Service_NIM, "called"); + } + + void GetResult(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_NIM, "called"); + } + + void Cancel(Kernel::HLERequestContext& ctx) { + finished_event->Clear(); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_DEBUG(Service_NIM, "called"); + } + + void IsProcessing(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u32>(0); // We instantly process the request + LOG_DEBUG(Service_NIM, "called"); + } + + void GetServerTime(Kernel::HLERequestContext& ctx) { + const s64 server_time{std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::system_clock::now().time_since_epoch()) + .count()}; + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<s64>(server_time); + LOG_DEBUG(Service_NIM, "called"); + } +}; + class NTC final : public ServiceFramework<NTC> { public: explicit NTC() : ServiceFramework{"ntc"} { // clang-format off static const FunctionInfo functions[] = { - {0, nullptr, "OpenEnsureNetworkClockAvailabilityService"}, - {100, nullptr, "SuspendAutonomicTimeCorrection"}, - {101, nullptr, "ResumeAutonomicTimeCorrection"}, + {0, &NTC::OpenEnsureNetworkClockAvailabilityService, "OpenEnsureNetworkClockAvailabilityService"}, + {100, &NTC::SuspendAutonomicTimeCorrection, "SuspendAutonomicTimeCorrection"}, + {101, &NTC::ResumeAutonomicTimeCorrection, "ResumeAutonomicTimeCorrection"}, }; // clang-format on RegisterHandlers(functions); } + +private: + void OpenEnsureNetworkClockAvailabilityService(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushIpcInterface<IEnsureNetworkClockAvailabilityService>(); + LOG_DEBUG(Service_NIM, "called"); + } + + // TODO(ogniK): Do we need these? + void SuspendAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_NIM, "(STUBBED) called"); + } + + void ResumeAutonomicTimeCorrection(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_NIM, "(STUBBED) called"); + } }; void InstallInterfaces(SM::ServiceManager& sm) { diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index 096f0fd52..464e79d01 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -108,7 +108,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { auto client_port = service_manager->GetServicePort(name); if (client_port.Failed()) { - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(client_port.Code()); LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, client_port.Code().raw); if (name.length() == 0) @@ -121,8 +121,7 @@ void SM::GetService(Kernel::HLERequestContext& ctx) { ASSERT(session.Succeeded()); if (session.Succeeded()) { LOG_DEBUG(Service_SM, "called service={} -> session={}", name, (*session)->GetObjectId()); - IPC::ResponseBuilder rb = - rp.MakeBuilder(2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles); + IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; rb.Push(session.Code()); rb.PushMoveObjects(std::move(session).Unwrap()); } diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index bb5f5b321..bc4f7a437 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -71,7 +71,7 @@ private: LOG_WARNING(Service_SSL, "(STUBBED) called"); IPC::RequestParser rp{ctx}; - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d0cde5ede..2ee60f1ec 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -650,7 +650,7 @@ private: u64 layer_id = rp.Pop<u64>(); u64 z_value = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -658,7 +658,7 @@ private: IPC::RequestParser rp{ctx}; u64 layer_id = rp.Pop<u64>(); bool visibility = rp.Pop<bool>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); @@ -747,7 +747,7 @@ private: IPC::RequestParser rp{ctx}; u64 display = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -761,7 +761,7 @@ private: u64 layer_id = nv_flinger->CreateLayer(display); - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push(layer_id); } @@ -772,7 +772,7 @@ private: u32 stack = rp.Pop<u32>(); u64 layer_id = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -780,7 +780,7 @@ private: IPC::RequestParser rp{ctx}; u64 layer_id = rp.Pop<u64>(); bool visibility = rp.Pop<bool>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, visibility); @@ -837,7 +837,7 @@ private: ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push<u64>(nv_flinger->OpenDisplay(name)); } @@ -847,7 +847,7 @@ private: IPC::RequestParser rp{ctx}; u64 display_id = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -856,7 +856,7 @@ private: IPC::RequestParser rp{ctx}; u64 display_id = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0); + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); if (Settings::values.use_docked_mode) { @@ -874,7 +874,7 @@ private: u32 scaling_mode = rp.Pop<u32>(); u64 unknown = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -882,7 +882,7 @@ private: IPC::RequestParser rp{ctx}; DisplayInfo display_info; ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push<u64>(1); LOG_WARNING(Service_VI, "(STUBBED) called"); @@ -903,7 +903,7 @@ private: u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0); + IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); } @@ -922,7 +922,7 @@ private: u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); NativeWindow native_window{buffer_queue_id}; - IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0); + IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); rb.Push(layer_id); rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize())); @@ -934,7 +934,7 @@ private: IPC::RequestParser rp{ctx}; u64 layer_id = rp.Pop<u64>(); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0); + IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } @@ -945,7 +945,7 @@ private: auto vsync_event = nv_flinger->GetVsyncEvent(display_id); - IPC::ResponseBuilder rb = rp.MakeBuilder(2, 1, 0); + IPC::ResponseBuilder rb{ctx, 2, 1}; rb.Push(RESULT_SUCCESS); rb.PushCopyObjects(vsync_event); } |
