diff options
Diffstat (limited to 'src/core/hle')
-rw-r--r-- | src/core/hle/kernel/process.cpp | 87 | ||||
-rw-r--r-- | src/core/hle/kernel/process.h | 55 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 46 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 58 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 13 | ||||
-rw-r--r-- | src/core/hle/service/audio/audren_u.cpp | 9 | ||||
-rw-r--r-- | src/core/hle/service/fatal/fatal.cpp | 141 | ||||
-rw-r--r-- | src/core/hle/service/fatal/fatal.h | 1 | ||||
-rw-r--r-- | src/core/hle/service/fatal/fatal_u.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid/irs.cpp | 158 | ||||
-rw-r--r-- | src/core/hle/service/hid/irs.h | 27 | ||||
-rw-r--r-- | src/core/hle/service/ssl/ssl.cpp | 6 |
12 files changed, 470 insertions, 133 deletions
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 914bbe0a1..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" @@ -128,6 +130,91 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) { 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) { const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions, MemoryState memory_state) { 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..c9d212a4c 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(); @@ -1039,7 +1017,7 @@ static const FunctionDef SVC_Table[] = { {0x2B, nullptr, "FlushDataCache"}, {0x2C, nullptr, "MapPhysicalMemory"}, {0x2D, nullptr, "UnmapPhysicalMemory"}, - {0x2E, nullptr, "GetNextThreadInfo"}, + {0x2E, nullptr, "GetFutureThreadInfo"}, {0x2F, nullptr, "GetLastThreadInfo"}, {0x30, nullptr, "GetResourceLimitLimitValue"}, {0x31, nullptr, "GetResourceLimitCurrentValue"}, @@ -1065,11 +1043,11 @@ static const FunctionDef SVC_Table[] = { {0x45, nullptr, "CreateEvent"}, {0x46, nullptr, "Unknown"}, {0x47, nullptr, "Unknown"}, - {0x48, nullptr, "AllocateUnsafeMemory"}, - {0x49, nullptr, "FreeUnsafeMemory"}, - {0x4A, nullptr, "SetUnsafeAllocationLimit"}, - {0x4B, nullptr, "CreateJitMemory"}, - {0x4C, nullptr, "MapJitMemory"}, + {0x48, nullptr, "MapPhysicalMemoryUnsafe"}, + {0x49, nullptr, "UnmapPhysicalMemoryUnsafe"}, + {0x4A, nullptr, "SetUnsafeLimit"}, + {0x4B, nullptr, "CreateCodeMemory"}, + {0x4C, nullptr, "ControlCodeMemory"}, {0x4D, nullptr, "SleepSystem"}, {0x4E, nullptr, "ReadWriteRegister"}, {0x4F, nullptr, "SetProcessActivity"}, @@ -1104,7 +1082,7 @@ static const FunctionDef SVC_Table[] = { {0x6C, nullptr, "SetHardwareBreakPoint"}, {0x6D, nullptr, "GetDebugThreadParam"}, {0x6E, nullptr, "Unknown"}, - {0x6F, nullptr, "GetMemoryInfo"}, + {0x6F, nullptr, "GetSystemInfo"}, {0x70, nullptr, "CreatePort"}, {0x71, nullptr, "ManageNamedPort"}, {0x72, nullptr, "ConnectToPort"}, diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index c2d7535c9..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 diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 91e9b79ec..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>(); }; /** diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 06ac6372d..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); diff --git a/src/core/hle/service/fatal/fatal.cpp b/src/core/hle/service/fatal/fatal.cpp index b436ce4e6..6de7edf9e 100644 --- a/src/core/hle/service/fatal/fatal.cpp +++ b/src/core/hle/service/fatal/fatal.cpp @@ -2,8 +2,17 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <array> +#include <cstring> +#include <ctime> +#include <fmt/time.h> +#include "common/common_paths.h" +#include "common/file_util.h" #include "common/logging/log.h" +#include "common/scm_rev.h" +#include "common/swap.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/fatal/fatal.h" #include "core/hle/service/fatal/fatal_p.h" #include "core/hle/service/fatal/fatal_u.h" @@ -15,16 +24,142 @@ Module::Interface::Interface(std::shared_ptr<Module> module, const char* name) Module::Interface::~Interface() = default; +struct FatalInfo { + std::array<u64_le, 31> registers{}; // TODO(ogniK): See if this actually is registers or + // not(find a game which has non zero valeus) + u64_le unk0{}; + u64_le unk1{}; + u64_le unk2{}; + u64_le unk3{}; + u64_le unk4{}; + u64_le unk5{}; + u64_le unk6{}; + + std::array<u64_le, 32> backtrace{}; + u64_le unk7{}; + u64_le unk8{}; + u32_le backtrace_size{}; + u32_le unk9{}; + u32_le unk10{}; // TODO(ogniK): Is this even used or is it just padding? +}; +static_assert(sizeof(FatalInfo) == 0x250, "FatalInfo is an invalid size"); + +enum class FatalType : u32 { + ErrorReportAndScreen = 0, + ErrorReport = 1, + ErrorScreen = 2, +}; + +static void GenerateErrorReport(ResultCode error_code, const FatalInfo& info) { + const auto title_id = Core::CurrentProcess()->program_id; + std::string crash_report = + fmt::format("Yuzu {}-{} crash report\n" + "Title ID: {:016x}\n" + "Result: 0x{:X} ({:04}-{:04d})\n" + "\n", + Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw, + 2000 + static_cast<u32>(error_code.module.Value()), + static_cast<u32>(error_code.description.Value()), info.unk8, info.unk7); + if (info.backtrace_size != 0x0) { + crash_report += "Registers:\n"; + // TODO(ogniK): This is just a guess, find a game which actually has non zero values + for (size_t i = 0; i < info.registers.size(); i++) { + crash_report += + fmt::format(" X[{:02d}]: {:016x}\n", i, info.registers[i]); + } + crash_report += fmt::format(" Unknown 0: {:016x}\n", info.unk0); + crash_report += fmt::format(" Unknown 1: {:016x}\n", info.unk1); + crash_report += fmt::format(" Unknown 2: {:016x}\n", info.unk2); + crash_report += fmt::format(" Unknown 3: {:016x}\n", info.unk3); + crash_report += fmt::format(" Unknown 4: {:016x}\n", info.unk4); + crash_report += fmt::format(" Unknown 5: {:016x}\n", info.unk5); + crash_report += fmt::format(" Unknown 6: {:016x}\n", info.unk6); + crash_report += "\nBacktrace:\n"; + for (size_t i = 0; i < info.backtrace_size; i++) { + crash_report += + fmt::format(" Backtrace[{:02d}]: {:016x}\n", i, info.backtrace[i]); + } + crash_report += fmt::format("\nUnknown 7: 0x{:016x}\n", info.unk7); + crash_report += fmt::format("Unknown 8: 0x{:016x}\n", info.unk8); + crash_report += fmt::format("Unknown 9: 0x{:016x}\n", info.unk9); + crash_report += fmt::format("Unknown 10: 0x{:016x}\n", info.unk10); + } + + LOG_ERROR(Service_Fatal, "{}", crash_report); + + const std::string crashreport_dir = + FileUtil::GetUserPath(FileUtil::UserPath::LogDir) + "crash_logs"; + + if (!FileUtil::CreateFullPath(crashreport_dir)) { + LOG_ERROR( + Service_Fatal, + "Unable to create crash report directory. Possible log directory permissions issue."); + return; + } + + const std::time_t t = std::time(nullptr); + const std::string crashreport_filename = + fmt::format("{}/{:016x}-{:%F-%H%M%S}.log", crashreport_dir, title_id, *std::localtime(&t)); + + auto file = FileUtil::IOFile(crashreport_filename, "wb"); + if (file.IsOpen()) { + file.WriteString(crash_report); + LOG_ERROR(Service_Fatal, "Saving error report to {}", crashreport_filename); + } else { + LOG_ERROR(Service_Fatal, "Failed to save error report to {}", crashreport_filename); + } +} + +static void ThrowFatalError(ResultCode error_code, FatalType fatal_type, const FatalInfo& info) { + LOG_ERROR(Service_Fatal, "Threw fatal error type {}", static_cast<u32>(fatal_type)); + switch (fatal_type) { + case FatalType::ErrorReportAndScreen: + GenerateErrorReport(error_code, info); + [[fallthrough]]; + case FatalType::ErrorScreen: + // Since we have no fatal:u error screen. We should just kill execution instead + ASSERT(false); + break; + // Should not throw a fatal screen but should generate an error report + case FatalType::ErrorReport: + GenerateErrorReport(error_code, info); + break; + }; +} + +void Module::Interface::ThrowFatal(Kernel::HLERequestContext& ctx) { + LOG_ERROR(Service_Fatal, "called"); + IPC::RequestParser rp{ctx}; + auto error_code = rp.Pop<ResultCode>(); + + ThrowFatalError(error_code, FatalType::ErrorScreen, {}); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + void Module::Interface::ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx) { + LOG_ERROR(Service_Fatal, "called"); IPC::RequestParser rp(ctx); - u32 error_code = rp.Pop<u32>(); - LOG_WARNING(Service_Fatal, "(STUBBED) called, error_code=0x{:X}", error_code); + auto error_code = rp.Pop<ResultCode>(); + auto fatal_type = rp.PopEnum<FatalType>(); + + ThrowFatalError(error_code, fatal_type, {}); // No info is passed with ThrowFatalWithPolicy IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } void Module::Interface::ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_Fatal, "(STUBBED) called"); + LOG_ERROR(Service_Fatal, "called"); + IPC::RequestParser rp(ctx); + auto error_code = rp.Pop<ResultCode>(); + auto fatal_type = rp.PopEnum<FatalType>(); + auto fatal_info = ctx.ReadBuffer(); + FatalInfo info{}; + + ASSERT_MSG(fatal_info.size() == sizeof(FatalInfo), "Invalid fatal info buffer size!"); + std::memcpy(&info, fatal_info.data(), sizeof(FatalInfo)); + + ThrowFatalError(error_code, fatal_type, info); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } diff --git a/src/core/hle/service/fatal/fatal.h b/src/core/hle/service/fatal/fatal.h index 4d9a5be52..09371ff7f 100644 --- a/src/core/hle/service/fatal/fatal.h +++ b/src/core/hle/service/fatal/fatal.h @@ -15,6 +15,7 @@ public: explicit Interface(std::shared_ptr<Module> module, const char* name); ~Interface() override; + void ThrowFatal(Kernel::HLERequestContext& ctx); void ThrowFatalWithPolicy(Kernel::HLERequestContext& ctx); void ThrowFatalWithCpuContext(Kernel::HLERequestContext& ctx); diff --git a/src/core/hle/service/fatal/fatal_u.cpp b/src/core/hle/service/fatal/fatal_u.cpp index befc307cf..1572a2051 100644 --- a/src/core/hle/service/fatal/fatal_u.cpp +++ b/src/core/hle/service/fatal/fatal_u.cpp @@ -8,7 +8,7 @@ namespace Service::Fatal { Fatal_U::Fatal_U(std::shared_ptr<Module> module) : Module::Interface(std::move(module), "fatal:u") { static const FunctionInfo functions[] = { - {0, nullptr, "ThrowFatal"}, + {0, &Fatal_U::ThrowFatal, "ThrowFatal"}, {1, &Fatal_U::ThrowFatalWithPolicy, "ThrowFatalWithPolicy"}, {2, &Fatal_U::ThrowFatalWithCpuContext, "ThrowFatalWithCpuContext"}, }; diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp index e587ad0d8..872e3c344 100644 --- a/src/core/hle/service/hid/irs.cpp +++ b/src/core/hle/service/hid/irs.cpp @@ -2,6 +2,11 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/swap.h" +#include "core/core.h" +#include "core/core_timing.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/shared_memory.h" #include "core/hle/service/hid/irs.h" namespace Service::HID { @@ -9,28 +14,145 @@ namespace Service::HID { IRS::IRS() : ServiceFramework{"irs"} { // clang-format off static const FunctionInfo functions[] = { - {302, nullptr, "ActivateIrsensor"}, - {303, nullptr, "DeactivateIrsensor"}, - {304, nullptr, "GetIrsensorSharedMemoryHandle"}, - {305, nullptr, "StopImageProcessor"}, - {306, nullptr, "RunMomentProcessor"}, - {307, nullptr, "RunClusteringProcessor"}, - {308, nullptr, "RunImageTransferProcessor"}, - {309, nullptr, "GetImageTransferProcessorState"}, - {310, nullptr, "RunTeraPluginProcessor"}, - {311, nullptr, "GetNpadIrCameraHandle"}, - {312, nullptr, "RunPointingProcessor"}, - {313, nullptr, "SuspendImageProcessor"}, - {314, nullptr, "CheckFirmwareVersion"}, - {315, nullptr, "SetFunctionLevel"}, - {316, nullptr, "RunImageTransferExProcessor"}, - {317, nullptr, "RunIrLedProcessor"}, - {318, nullptr, "StopImageProcessorAsync"}, - {319, nullptr, "ActivateIrsensorWithFunctionLevel"}, + {302, &IRS::ActivateIrsensor, "ActivateIrsensor"}, + {303, &IRS::DeactivateIrsensor, "DeactivateIrsensor"}, + {304, &IRS::GetIrsensorSharedMemoryHandle, "GetIrsensorSharedMemoryHandle"}, + {305, &IRS::StopImageProcessor, "StopImageProcessor"}, + {306, &IRS::RunMomentProcessor, "RunMomentProcessor"}, + {307, &IRS::RunClusteringProcessor, "RunClusteringProcessor"}, + {308, &IRS::RunImageTransferProcessor, "RunImageTransferProcessor"}, + {309, &IRS::GetImageTransferProcessorState, "GetImageTransferProcessorState"}, + {310, &IRS::RunTeraPluginProcessor, "RunTeraPluginProcessor"}, + {311, &IRS::GetNpadIrCameraHandle, "GetNpadIrCameraHandle"}, + {312, &IRS::RunPointingProcessor, "RunPointingProcessor"}, + {313, &IRS::SuspendImageProcessor, "SuspendImageProcessor"}, + {314, &IRS::CheckFirmwareVersion, "CheckFirmwareVersion"}, + {315, &IRS::SetFunctionLevel, "SetFunctionLevel"}, + {316, &IRS::RunImageTransferExProcessor, "RunImageTransferExProcessor"}, + {317, &IRS::RunIrLedProcessor, "RunIrLedProcessor"}, + {318, &IRS::StopImageProcessorAsync, "StopImageProcessorAsync"}, + {319, &IRS::ActivateIrsensorWithFunctionLevel, "ActivateIrsensorWithFunctionLevel"}, }; // clang-format on RegisterHandlers(functions); + + auto& kernel = Core::System::GetInstance().Kernel(); + shared_mem = Kernel::SharedMemory::Create( + kernel, nullptr, 0x8000, Kernel::MemoryPermission::ReadWrite, + Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "IRS:SharedMemory"); +} + +void IRS::ActivateIrsensor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::DeactivateIrsensor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(shared_mem); + LOG_DEBUG(Service_IRS, "called"); +} + +void IRS::StopImageProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunMomentProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunClusteringProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunImageTransferProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::GetImageTransferProcessorState(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 5}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u64>(CoreTiming::GetTicks()); + rb.PushRaw<u32>(0); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunTeraPluginProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.PushRaw<u32>(device_handle); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunPointingProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::SuspendImageProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::CheckFirmwareVersion(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::SetFunctionLevel(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunImageTransferExProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::RunIrLedProcessor(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::StopImageProcessorAsync(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); +} + +void IRS::ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + LOG_WARNING(Service_IRS, "(STUBBED) called"); } IRS::~IRS() = default; diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h index 6fb16b45d..12de6bfb3 100644 --- a/src/core/hle/service/hid/irs.h +++ b/src/core/hle/service/hid/irs.h @@ -4,14 +4,41 @@ #pragma once +#include "core/hle/kernel/object.h" #include "core/hle/service/service.h" +namespace Kernel { +class SharedMemory; +} + namespace Service::HID { class IRS final : public ServiceFramework<IRS> { public: explicit IRS(); ~IRS() override; + +private: + void ActivateIrsensor(Kernel::HLERequestContext& ctx); + void DeactivateIrsensor(Kernel::HLERequestContext& ctx); + void GetIrsensorSharedMemoryHandle(Kernel::HLERequestContext& ctx); + void StopImageProcessor(Kernel::HLERequestContext& ctx); + void RunMomentProcessor(Kernel::HLERequestContext& ctx); + void RunClusteringProcessor(Kernel::HLERequestContext& ctx); + void RunImageTransferProcessor(Kernel::HLERequestContext& ctx); + void GetImageTransferProcessorState(Kernel::HLERequestContext& ctx); + void RunTeraPluginProcessor(Kernel::HLERequestContext& ctx); + void GetNpadIrCameraHandle(Kernel::HLERequestContext& ctx); + void RunPointingProcessor(Kernel::HLERequestContext& ctx); + void SuspendImageProcessor(Kernel::HLERequestContext& ctx); + void CheckFirmwareVersion(Kernel::HLERequestContext& ctx); + void SetFunctionLevel(Kernel::HLERequestContext& ctx); + void RunImageTransferExProcessor(Kernel::HLERequestContext& ctx); + void RunIrLedProcessor(Kernel::HLERequestContext& ctx); + void StopImageProcessorAsync(Kernel::HLERequestContext& ctx); + void ActivateIrsensorWithFunctionLevel(Kernel::HLERequestContext& ctx); + Kernel::SharedPtr<Kernel::SharedMemory> shared_mem; + const u32 device_handle{0xABCD}; }; class IRS_SYS final : public ServiceFramework<IRS_SYS> { diff --git a/src/core/hle/service/ssl/ssl.cpp b/src/core/hle/service/ssl/ssl.cpp index fe0a318ee..bc4f7a437 100644 --- a/src/core/hle/service/ssl/ssl.cpp +++ b/src/core/hle/service/ssl/ssl.cpp @@ -103,6 +103,7 @@ public: } private: + u32 ssl_version{}; void CreateContext(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_SSL, "(STUBBED) called"); @@ -112,10 +113,9 @@ private: } void SetInterfaceVersion(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service_SSL, "(STUBBED) called"); + LOG_DEBUG(Service_SSL, "called"); IPC::RequestParser rp{ctx}; - u32 unk1 = rp.Pop<u32>(); // Probably minor/major? - u32 unk2 = rp.Pop<u32>(); // TODO(ogniK): Figure out what this does + ssl_version = rp.Pop<u32>(); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); |