diff options
Diffstat (limited to 'src/core/hle/service/ldr_ro/ldr_ro.cpp')
-rw-r--r-- | src/core/hle/service/ldr_ro/ldr_ro.cpp | 208 |
1 files changed, 115 insertions, 93 deletions
diff --git a/src/core/hle/service/ldr_ro/ldr_ro.cpp b/src/core/hle/service/ldr_ro/ldr_ro.cpp index 8ba73ea8d..ae5d3921f 100644 --- a/src/core/hle/service/ldr_ro/ldr_ro.cpp +++ b/src/core/hle/service/ldr_ro/ldr_ro.cpp @@ -18,24 +18,33 @@ namespace LDR_RO { -static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 - ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); -static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 - ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Permanent); -static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F - ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, ErrorLevel::Usage); -static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 - ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); -static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 - ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, ErrorLevel::Permanent); -static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F - ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage); -static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 - ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); -static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D - ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, ErrorLevel::Permanent); -static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 - ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent); +static const ResultCode ERROR_ALREADY_INITIALIZED = // 0xD9612FF9 + ResultCode(ErrorDescription::AlreadyInitialized, ErrorModule::RO, ErrorSummary::Internal, + ErrorLevel::Permanent); +static const ResultCode ERROR_NOT_INITIALIZED = // 0xD9612FF8 + ResultCode(ErrorDescription::NotInitialized, ErrorModule::RO, ErrorSummary::Internal, + ErrorLevel::Permanent); +static const ResultCode ERROR_BUFFER_TOO_SMALL = // 0xE0E12C1F + ResultCode(static_cast<ErrorDescription>(31), ErrorModule::RO, ErrorSummary::InvalidArgument, + ErrorLevel::Usage); +static const ResultCode ERROR_MISALIGNED_ADDRESS = // 0xD9012FF1 + ResultCode(ErrorDescription::MisalignedAddress, ErrorModule::RO, ErrorSummary::WrongArgument, + ErrorLevel::Permanent); +static const ResultCode ERROR_MISALIGNED_SIZE = // 0xD9012FF2 + ResultCode(ErrorDescription::MisalignedSize, ErrorModule::RO, ErrorSummary::WrongArgument, + ErrorLevel::Permanent); +static const ResultCode ERROR_ILLEGAL_ADDRESS = // 0xE1612C0F + ResultCode(static_cast<ErrorDescription>(15), ErrorModule::RO, ErrorSummary::Internal, + ErrorLevel::Usage); +static const ResultCode ERROR_INVALID_MEMORY_STATE = // 0xD8A12C08 + ResultCode(static_cast<ErrorDescription>(8), ErrorModule::RO, ErrorSummary::InvalidState, + ErrorLevel::Permanent); +static const ResultCode ERROR_NOT_LOADED = // 0xD8A12C0D + ResultCode(static_cast<ErrorDescription>(13), ErrorModule::RO, ErrorSummary::InvalidState, + ErrorLevel::Permanent); +static const ResultCode ERROR_INVALID_DESCRIPTOR = // 0xD9001830 + ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, + ErrorSummary::WrongArgument, ErrorLevel::Permanent); static MemorySynchronizer memory_synchronizer; @@ -44,10 +53,10 @@ static VAddr loaded_crs; ///< the virtual address of the static module static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { auto vma = Kernel::g_current_process->vm_manager.FindVMA(buffer_ptr); - return vma != Kernel::g_current_process->vm_manager.vma_map.end() - && vma->second.base + vma->second.size >= buffer_ptr + size - && vma->second.permissions == Kernel::VMAPermission::ReadWrite - && vma->second.meminfo_state == Kernel::MemoryState::Private; + return vma != Kernel::g_current_process->vm_manager.vma_map.end() && + vma->second.base + vma->second.size >= buffer_ptr + size && + vma->second.permissions == Kernel::VMAPermission::ReadWrite && + vma->second.meminfo_state == Kernel::MemoryState::Private; } /** @@ -66,13 +75,14 @@ static bool VerifyBufferState(VAddr buffer_ptr, u32 size) { static void Initialize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); VAddr crs_buffer_ptr = cmd_buff[1]; - u32 crs_size = cmd_buff[2]; - VAddr crs_address = cmd_buff[3]; - u32 descriptor = cmd_buff[4]; - u32 process = cmd_buff[5]; + u32 crs_size = cmd_buff[2]; + VAddr crs_address = cmd_buff[3]; + u32 descriptor = cmd_buff[4]; + u32 process = cmd_buff[5]; - LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, descriptor=0x%08X, process=0x%08X", - crs_buffer_ptr, crs_address, crs_size, descriptor, process); + LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, crs_address=0x%08X, crs_size=0x%X, " + "descriptor=0x%08X, process=0x%08X", + crs_buffer_ptr, crs_address, crs_size, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -119,7 +129,8 @@ static void Initialize(Service::Interface* self) { return; } - if (crs_address < Memory::PROCESS_IMAGE_VADDR || crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { + if (crs_address < Memory::PROCESS_IMAGE_VADDR || + crs_address + crs_size > Memory::PROCESS_IMAGE_VADDR_END) { LOG_ERROR(Service_LDR, "CRS mapping address is not in the process image region"); cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; return; @@ -131,14 +142,17 @@ static void Initialize(Service::Interface* self) { // TODO(wwylele): should be memory aliasing std::shared_ptr<std::vector<u8>> crs_mem = std::make_shared<std::vector<u8>>(crs_size); Memory::ReadBlock(crs_buffer_ptr, crs_mem->data(), crs_size); - result = Kernel::g_current_process->vm_manager.MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code).Code(); + result = Kernel::g_current_process->vm_manager + .MapMemoryBlock(crs_address, crs_mem, 0, crs_size, Kernel::MemoryState::Code) + .Code(); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); cmd_buff[1] = result.raw; return; } - result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, Kernel::VMAPermission::Read); + result = Kernel::g_current_process->vm_manager.ReprotectRange(crs_address, crs_size, + Kernel::VMAPermission::Read); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); cmd_buff[1] = result.raw; @@ -186,9 +200,9 @@ static void Initialize(Service::Interface* self) { static void LoadCRR(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 crr_buffer_ptr = cmd_buff[1]; - u32 crr_size = cmd_buff[2]; - u32 descriptor = cmd_buff[3]; - u32 process = cmd_buff[4]; + u32 crr_size = cmd_buff[2]; + u32 descriptor = cmd_buff[3]; + u32 process = cmd_buff[4]; if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -200,7 +214,8 @@ static void LoadCRR(Service::Interface* self) { cmd_buff[0] = IPC::MakeHeader(2, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, descriptor=0x%08X, process=0x%08X", + LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, crr_size=0x%08X, " + "descriptor=0x%08X, process=0x%08X", crr_buffer_ptr, crr_size, descriptor, process); } @@ -218,8 +233,8 @@ static void LoadCRR(Service::Interface* self) { static void UnloadCRR(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); u32 crr_buffer_ptr = cmd_buff[1]; - u32 descriptor = cmd_buff[2]; - u32 process = cmd_buff[3]; + u32 descriptor = cmd_buff[2]; + u32 process = cmd_buff[3]; if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -231,7 +246,8 @@ static void UnloadCRR(Service::Interface* self) { cmd_buff[0] = IPC::MakeHeader(3, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_WARNING(Service_LDR, "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", + LOG_WARNING(Service_LDR, + "(STUBBED) called, crr_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", crr_buffer_ptr, descriptor, process); } @@ -263,27 +279,28 @@ static void UnloadCRR(Service::Interface* self) { */ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { u32* cmd_buff = Kernel::GetCommandBuffer(); - VAddr cro_buffer_ptr = cmd_buff[1]; - VAddr cro_address = cmd_buff[2]; - u32 cro_size = cmd_buff[3]; + VAddr cro_buffer_ptr = cmd_buff[1]; + VAddr cro_address = cmd_buff[2]; + u32 cro_size = cmd_buff[3]; VAddr data_segment_address = cmd_buff[4]; - u32 zero = cmd_buff[5]; - u32 data_segment_size = cmd_buff[6]; - u32 bss_segment_address = cmd_buff[7]; - u32 bss_segment_size = cmd_buff[8]; - bool auto_link = (cmd_buff[9] & 0xFF) != 0; - u32 fix_level = cmd_buff[10]; - VAddr crr_address = cmd_buff[11]; - u32 descriptor = cmd_buff[12]; - u32 process = cmd_buff[13]; - - LOG_DEBUG(Service_LDR, "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " - "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, bss_segment_address=0x%08X, bss_segment_size=0x%X, " - "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", - link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, - data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, - auto_link ? "true" : "false", fix_level, crr_address, descriptor, process - ); + u32 zero = cmd_buff[5]; + u32 data_segment_size = cmd_buff[6]; + u32 bss_segment_address = cmd_buff[7]; + u32 bss_segment_size = cmd_buff[8]; + bool auto_link = (cmd_buff[9] & 0xFF) != 0; + u32 fix_level = cmd_buff[10]; + VAddr crr_address = cmd_buff[11]; + u32 descriptor = cmd_buff[12]; + u32 process = cmd_buff[13]; + + LOG_DEBUG(Service_LDR, + "called (%s), cro_buffer_ptr=0x%08X, cro_address=0x%08X, cro_size=0x%X, " + "data_segment_address=0x%08X, zero=%d, data_segment_size=0x%X, " + "bss_segment_address=0x%08X, bss_segment_size=0x%X, " + "auto_link=%s, fix_level=%d, crr_address=0x%08X, descriptor=0x%08X, process=0x%08X", + link_on_load_bug_fix ? "new" : "old", cro_buffer_ptr, cro_address, cro_size, + data_segment_address, zero, data_segment_size, bss_segment_address, bss_segment_size, + auto_link ? "true" : "false", fix_level, crr_address, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -330,8 +347,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { return; } - if (cro_address < Memory::PROCESS_IMAGE_VADDR - || cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { + if (cro_address < Memory::PROCESS_IMAGE_VADDR || + cro_address + cro_size > Memory::PROCESS_IMAGE_VADDR_END) { LOG_ERROR(Service_LDR, "CRO mapping address is not in the process image region"); cmd_buff[1] = ERROR_ILLEGAL_ADDRESS.raw; return; @@ -339,7 +356,9 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { if (zero) { LOG_ERROR(Service_LDR, "Zero is not zero %d", zero); - cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, ErrorSummary::Internal, ErrorLevel::Usage).raw; + cmd_buff[1] = ResultCode(static_cast<ErrorDescription>(29), ErrorModule::RO, + ErrorSummary::Internal, ErrorLevel::Usage) + .raw; return; } @@ -349,14 +368,17 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { // TODO(wwylele): should be memory aliasing std::shared_ptr<std::vector<u8>> cro_mem = std::make_shared<std::vector<u8>>(cro_size); Memory::ReadBlock(cro_buffer_ptr, cro_mem->data(), cro_size); - result = Kernel::g_current_process->vm_manager.MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code).Code(); + result = Kernel::g_current_process->vm_manager + .MapMemoryBlock(cro_address, cro_mem, 0, cro_size, Kernel::MemoryState::Code) + .Code(); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error mapping memory block %08X", result.raw); cmd_buff[1] = result.raw; return; } - result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, Kernel::VMAPermission::Read); + result = Kernel::g_current_process->vm_manager.ReprotectRange(cro_address, cro_size, + Kernel::VMAPermission::Read); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); @@ -384,7 +406,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { return; } - result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, bss_segment_address, bss_segment_size, false); + result = cro.Rebase(loaded_crs, cro_size, data_segment_address, data_segment_size, + bss_segment_address, bss_segment_size, false); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error rebasing CRO %08X", result.raw); Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); @@ -409,7 +432,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { // TODO(wwylele): verify the behaviour when buffer_ptr == address if (cro_buffer_ptr != cro_address) { if (fix_size != cro_size) { - result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, cro_size - fix_size); + result = Kernel::g_current_process->vm_manager.UnmapRange(cro_address + fix_size, + cro_size - fix_size); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error unmapping memory block %08X", result.raw); Kernel::g_current_process->vm_manager.UnmapRange(cro_address, cro_size); @@ -426,7 +450,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { u32 exe_size; std::tie(exe_begin, exe_size) = cro.GetExecutablePages(); if (exe_begin) { - result = Kernel::g_current_process->vm_manager.ReprotectRange(exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); + result = Kernel::g_current_process->vm_manager.ReprotectRange( + exe_begin, exe_size, Kernel::VMAPermission::ReadExecute); if (result.IsError()) { LOG_ERROR(Service_LDR, "Error reprotecting memory block %08X", result.raw); Kernel::g_current_process->vm_manager.UnmapRange(cro_address, fix_size); @@ -437,8 +462,8 @@ static void LoadCRO(Service::Interface* self, bool link_on_load_bug_fix) { Core::g_app_core->ClearInstructionCache(); - LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", - cro.ModuleName().data(), cro_address, cro_address+fix_size); + LOG_INFO(Service_LDR, "CRO \"%s\" loaded at 0x%08X, fixed_end=0x%08X", cro.ModuleName().data(), + cro_address, cro_address + fix_size); cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[2] = fix_size; @@ -464,14 +489,15 @@ static void LoadCRO(Service::Interface* self) { */ static void UnloadCRO(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - VAddr cro_address = cmd_buff[1]; - u32 zero = cmd_buff[2]; - VAddr cro_buffer_ptr = cmd_buff[3]; - u32 descriptor = cmd_buff[4]; - u32 process = cmd_buff[5]; + VAddr cro_address = cmd_buff[1]; + u32 zero = cmd_buff[2]; + VAddr cro_buffer_ptr = cmd_buff[3]; + u32 descriptor = cmd_buff[4]; + u32 process = cmd_buff[5]; - LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", - cro_address, zero, cro_buffer_ptr, descriptor, process); + LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, zero=%d, cro_buffer_ptr=0x%08X, " + "descriptor=0x%08X, process=0x%08X", + cro_address, zero, cro_buffer_ptr, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -558,11 +584,11 @@ static void UnloadCRO(Service::Interface* self) { static void LinkCRO(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); VAddr cro_address = cmd_buff[1]; - u32 descriptor = cmd_buff[2]; - u32 process = cmd_buff[3]; + u32 descriptor = cmd_buff[2]; + u32 process = cmd_buff[3]; LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", - cro_address, descriptor, process); + cro_address, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -620,11 +646,11 @@ static void LinkCRO(Service::Interface* self) { static void UnlinkCRO(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); VAddr cro_address = cmd_buff[1]; - u32 descriptor = cmd_buff[2]; - u32 process = cmd_buff[3]; + u32 descriptor = cmd_buff[2]; + u32 process = cmd_buff[3]; LOG_DEBUG(Service_LDR, "called, cro_address=0x%08X, descriptor=0x%08X, process=0x%08X", - cro_address, descriptor, process); + cro_address, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -682,11 +708,11 @@ static void UnlinkCRO(Service::Interface* self) { static void Shutdown(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); VAddr crs_buffer_ptr = cmd_buff[1]; - u32 descriptor = cmd_buff[2]; - u32 process = cmd_buff[3]; + u32 descriptor = cmd_buff[2]; + u32 process = cmd_buff[3]; LOG_DEBUG(Service_LDR, "called, crs_buffer_ptr=0x%08X, descriptor=0x%08X, process=0x%08X", - crs_buffer_ptr, descriptor, process); + crs_buffer_ptr, descriptor, process); if (descriptor != 0) { LOG_ERROR(Service_LDR, "IPC handle descriptor failed validation (0x%X)", descriptor); @@ -724,15 +750,11 @@ static void Shutdown(Service::Interface* self) { } const Interface::FunctionInfo FunctionTable[] = { - {0x000100C2, Initialize, "Initialize"}, - {0x00020082, LoadCRR, "LoadCRR"}, - {0x00030042, UnloadCRR, "UnloadCRR"}, - {0x000402C2, LoadCRO<false>, "LoadCRO"}, - {0x000500C2, UnloadCRO, "UnloadCRO"}, - {0x00060042, LinkCRO, "LinkCRO"}, - {0x00070042, UnlinkCRO, "UnlinkCRO"}, - {0x00080042, Shutdown, "Shutdown"}, - {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, + {0x000100C2, Initialize, "Initialize"}, {0x00020082, LoadCRR, "LoadCRR"}, + {0x00030042, UnloadCRR, "UnloadCRR"}, {0x000402C2, LoadCRO<false>, "LoadCRO"}, + {0x000500C2, UnloadCRO, "UnloadCRO"}, {0x00060042, LinkCRO, "LinkCRO"}, + {0x00070042, UnlinkCRO, "UnlinkCRO"}, {0x00080042, Shutdown, "Shutdown"}, + {0x000902C2, LoadCRO<true>, "LoadCRO_New"}, }; //////////////////////////////////////////////////////////////////////////////////////////////////// |