diff options
| author | 2016-05-29 21:57:07 -0400 | |
|---|---|---|
| committer | 2016-05-29 21:57:07 -0400 | |
| commit | ab4b27f0f5760c7f378f29756d3ce631bafca1b2 (patch) | |
| tree | 6340ca66710e9603db24c051da0b8173b796d3c6 /src/core | |
| parent | Merge pull request #1756 from wwylele/config-cleanup (diff) | |
| parent | Memory: Handle RasterizerCachedMemory and RasterizerCachedSpecial page types ... (diff) | |
| download | yuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.tar.gz yuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.tar.xz yuzu-ab4b27f0f5760c7f378f29756d3ce631bafca1b2.zip | |
Merge pull request #1692 from Subv/rm_getpointer2
Memory: Remove most usages of GetPointer
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/file_sys/archive_backend.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/applets/mii_selector.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/applets/mii_selector.h | 4 | ||||
| -rw-r--r-- | src/core/hle/applets/swkbd.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 25 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/cfg/cfg.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/dsp_dsp.cpp | 17 | ||||
| -rw-r--r-- | src/core/hle/service/frd/frd.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/fs/archive.cpp | 22 | ||||
| -rw-r--r-- | src/core/hle/service/gsp_gpu.cpp | 83 | ||||
| -rw-r--r-- | src/core/hle/service/soc_u.cpp | 100 | ||||
| -rw-r--r-- | src/core/hle/service/ssl_c.cpp | 7 | ||||
| -rw-r--r-- | src/core/memory.cpp | 236 | ||||
| -rw-r--r-- | src/core/memory.h | 8 | ||||
| -rw-r--r-- | src/core/mmio.h | 6 |
17 files changed, 454 insertions, 138 deletions
diff --git a/src/core/file_sys/archive_backend.cpp b/src/core/file_sys/archive_backend.cpp index 97adf0e12..cc0aa7022 100644 --- a/src/core/file_sys/archive_backend.cpp +++ b/src/core/file_sys/archive_backend.cpp | |||
| @@ -19,22 +19,22 @@ Path::Path(LowPathType type, u32 size, u32 pointer) : type(type) { | |||
| 19 | switch (type) { | 19 | switch (type) { |
| 20 | case Binary: | 20 | case Binary: |
| 21 | { | 21 | { |
| 22 | u8* data = Memory::GetPointer(pointer); | 22 | binary.resize(size); |
| 23 | binary = std::vector<u8>(data, data + size); | 23 | Memory::ReadBlock(pointer, binary.data(), binary.size()); |
| 24 | break; | 24 | break; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | case Char: | 27 | case Char: |
| 28 | { | 28 | { |
| 29 | const char* data = reinterpret_cast<const char*>(Memory::GetPointer(pointer)); | 29 | string.resize(size - 1); // Data is always null-terminated. |
| 30 | string = std::string(data, size - 1); // Data is always null-terminated. | 30 | Memory::ReadBlock(pointer, &string[0], string.size()); |
| 31 | break; | 31 | break; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | case Wchar: | 34 | case Wchar: |
| 35 | { | 35 | { |
| 36 | const char16_t* data = reinterpret_cast<const char16_t*>(Memory::GetPointer(pointer)); | 36 | u16str.resize(size / 2 - 1); // Data is always null-terminated. |
| 37 | u16str = std::u16string(data, size/2 - 1); // Data is always null-terminated. | 37 | Memory::ReadBlock(pointer, &u16str[0], u16str.size() * sizeof(char16_t)); |
| 38 | break; | 38 | break; |
| 39 | } | 39 | } |
| 40 | 40 | ||
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp index bf39eca22..77f01d208 100644 --- a/src/core/hle/applets/mii_selector.cpp +++ b/src/core/hle/applets/mii_selector.cpp | |||
| @@ -32,9 +32,9 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
| 32 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. | 32 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. |
| 33 | // Create the SharedMemory that will hold the framebuffer data | 33 | // Create the SharedMemory that will hold the framebuffer data |
| 34 | Service::APT::CaptureBufferInfo capture_info; | 34 | Service::APT::CaptureBufferInfo capture_info; |
| 35 | ASSERT(sizeof(capture_info) == parameter.buffer_size); | 35 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); |
| 36 | 36 | ||
| 37 | memcpy(&capture_info, parameter.data, sizeof(capture_info)); | 37 | memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); |
| 38 | 38 | ||
| 39 | using Kernel::MemoryPermission; | 39 | using Kernel::MemoryPermission; |
| 40 | // Allocate a heap block of the required size for this applet. | 40 | // Allocate a heap block of the required size for this applet. |
| @@ -47,8 +47,7 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p | |||
| 47 | // Send the response message with the newly created SharedMemory | 47 | // Send the response message with the newly created SharedMemory |
| 48 | Service::APT::MessageParameter result; | 48 | Service::APT::MessageParameter result; |
| 49 | result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); | 49 | result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); |
| 50 | result.data = nullptr; | 50 | result.buffer.clear(); |
| 51 | result.buffer_size = 0; | ||
| 52 | result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | 51 | result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
| 53 | result.sender_id = static_cast<u32>(id); | 52 | result.sender_id = static_cast<u32>(id); |
| 54 | result.object = framebuffer_memory; | 53 | result.object = framebuffer_memory; |
| @@ -63,15 +62,17 @@ ResultCode MiiSelector::StartImpl(const Service::APT::AppletStartupParameter& pa | |||
| 63 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. | 62 | // TODO(Subv): Set the expected fields in the response buffer before resending it to the application. |
| 64 | // TODO(Subv): Reverse the parameter format for the Mii Selector | 63 | // TODO(Subv): Reverse the parameter format for the Mii Selector |
| 65 | 64 | ||
| 66 | if(parameter.buffer_size >= sizeof(u32)) { | 65 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); |
| 67 | // TODO: defaults return no error, but garbage in other unknown fields | 66 | |
| 68 | memset(parameter.data, 0, sizeof(u32)); | 67 | // TODO(Subv): Find more about this structure, result code 0 is enough to let most games continue. |
| 69 | } | 68 | MiiResult result; |
| 69 | memset(&result, 0, sizeof(result)); | ||
| 70 | result.result_code = 0; | ||
| 70 | 71 | ||
| 71 | // Let the application know that we're closing | 72 | // Let the application know that we're closing |
| 72 | Service::APT::MessageParameter message; | 73 | Service::APT::MessageParameter message; |
| 73 | message.buffer_size = parameter.buffer_size; | 74 | message.buffer.resize(sizeof(MiiResult)); |
| 74 | message.data = parameter.data; | 75 | std::memcpy(message.buffer.data(), &result, message.buffer.size()); |
| 75 | message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); | 76 | message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); |
| 76 | message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | 77 | message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
| 77 | message.sender_id = static_cast<u32>(id); | 78 | message.sender_id = static_cast<u32>(id); |
diff --git a/src/core/hle/applets/mii_selector.h b/src/core/hle/applets/mii_selector.h index be6b04642..24e8e721d 100644 --- a/src/core/hle/applets/mii_selector.h +++ b/src/core/hle/applets/mii_selector.h | |||
| @@ -24,7 +24,7 @@ struct MiiConfig { | |||
| 24 | u8 unk_004; | 24 | u8 unk_004; |
| 25 | INSERT_PADDING_BYTES(3); | 25 | INSERT_PADDING_BYTES(3); |
| 26 | u16 unk_008; | 26 | u16 unk_008; |
| 27 | INSERT_PADDING_BYTES(0x8C - 0xA); | 27 | INSERT_PADDING_BYTES(0x82); |
| 28 | u8 unk_08C; | 28 | u8 unk_08C; |
| 29 | INSERT_PADDING_BYTES(3); | 29 | INSERT_PADDING_BYTES(3); |
| 30 | u16 unk_090; | 30 | u16 unk_090; |
| @@ -75,6 +75,8 @@ public: | |||
| 75 | 75 | ||
| 76 | /// Whether this applet is currently running instead of the host application or not. | 76 | /// Whether this applet is currently running instead of the host application or not. |
| 77 | bool started; | 77 | bool started; |
| 78 | |||
| 79 | MiiConfig config; | ||
| 78 | }; | 80 | }; |
| 79 | 81 | ||
| 80 | } | 82 | } |
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp index 90c6adc65..d87bf3d57 100644 --- a/src/core/hle/applets/swkbd.cpp +++ b/src/core/hle/applets/swkbd.cpp | |||
| @@ -35,9 +35,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 35 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. | 35 | // The LibAppJustStarted message contains a buffer with the size of the framebuffer shared memory. |
| 36 | // Create the SharedMemory that will hold the framebuffer data | 36 | // Create the SharedMemory that will hold the framebuffer data |
| 37 | Service::APT::CaptureBufferInfo capture_info; | 37 | Service::APT::CaptureBufferInfo capture_info; |
| 38 | ASSERT(sizeof(capture_info) == parameter.buffer_size); | 38 | ASSERT(sizeof(capture_info) == parameter.buffer.size()); |
| 39 | 39 | ||
| 40 | memcpy(&capture_info, parameter.data, sizeof(capture_info)); | 40 | memcpy(&capture_info, parameter.buffer.data(), sizeof(capture_info)); |
| 41 | 41 | ||
| 42 | using Kernel::MemoryPermission; | 42 | using Kernel::MemoryPermission; |
| 43 | // Allocate a heap block of the required size for this applet. | 43 | // Allocate a heap block of the required size for this applet. |
| @@ -50,8 +50,7 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 50 | // Send the response message with the newly created SharedMemory | 50 | // Send the response message with the newly created SharedMemory |
| 51 | Service::APT::MessageParameter result; | 51 | Service::APT::MessageParameter result; |
| 52 | result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); | 52 | result.signal = static_cast<u32>(Service::APT::SignalType::LibAppFinished); |
| 53 | result.data = nullptr; | 53 | result.buffer.clear(); |
| 54 | result.buffer_size = 0; | ||
| 55 | result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | 54 | result.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
| 56 | result.sender_id = static_cast<u32>(id); | 55 | result.sender_id = static_cast<u32>(id); |
| 57 | result.object = framebuffer_memory; | 56 | result.object = framebuffer_memory; |
| @@ -61,9 +60,9 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con | |||
| 61 | } | 60 | } |
| 62 | 61 | ||
| 63 | ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { | 62 | ResultCode SoftwareKeyboard::StartImpl(Service::APT::AppletStartupParameter const& parameter) { |
| 64 | ASSERT_MSG(parameter.buffer_size == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); | 63 | ASSERT_MSG(parameter.buffer.size() == sizeof(config), "The size of the parameter (SoftwareKeyboardConfig) is wrong"); |
| 65 | 64 | ||
| 66 | memcpy(&config, parameter.data, parameter.buffer_size); | 65 | memcpy(&config, parameter.buffer.data(), parameter.buffer.size()); |
| 67 | text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); | 66 | text_memory = boost::static_pointer_cast<Kernel::SharedMemory, Kernel::Object>(parameter.object); |
| 68 | 67 | ||
| 69 | // TODO(Subv): Verify if this is the correct behavior | 68 | // TODO(Subv): Verify if this is the correct behavior |
| @@ -99,7 +98,7 @@ void SoftwareKeyboard::DrawScreenKeyboard() { | |||
| 99 | auto info = bottom_screen->framebuffer_info[bottom_screen->index]; | 98 | auto info = bottom_screen->framebuffer_info[bottom_screen->index]; |
| 100 | 99 | ||
| 101 | // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer | 100 | // TODO(Subv): Draw the HLE keyboard, for now just zero-fill the framebuffer |
| 102 | memset(Memory::GetPointer(info.address_left), 0, info.stride * 320); | 101 | Memory::ZeroBlock(info.address_left, info.stride * 320); |
| 103 | 102 | ||
| 104 | GSP_GPU::SetBufferSwap(1, info); | 103 | GSP_GPU::SetBufferSwap(1, info); |
| 105 | } | 104 | } |
| @@ -107,8 +106,8 @@ void SoftwareKeyboard::DrawScreenKeyboard() { | |||
| 107 | void SoftwareKeyboard::Finalize() { | 106 | void SoftwareKeyboard::Finalize() { |
| 108 | // Let the application know that we're closing | 107 | // Let the application know that we're closing |
| 109 | Service::APT::MessageParameter message; | 108 | Service::APT::MessageParameter message; |
| 110 | message.buffer_size = sizeof(SoftwareKeyboardConfig); | 109 | message.buffer.resize(sizeof(SoftwareKeyboardConfig)); |
| 111 | message.data = reinterpret_cast<u8*>(&config); | 110 | std::memcpy(message.buffer.data(), &config, message.buffer.size()); |
| 112 | message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); | 111 | message.signal = static_cast<u32>(Service::APT::SignalType::LibAppClosed); |
| 113 | message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); | 112 | message.destination_id = static_cast<u32>(Service::APT::AppletId::Application); |
| 114 | message.sender_id = static_cast<u32>(id); | 113 | message.sender_id = static_cast<u32>(id); |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 43def6146..3f6bec5fa 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -403,7 +403,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 403 | priority = new_priority; | 403 | priority = new_priority; |
| 404 | } | 404 | } |
| 405 | 405 | ||
| 406 | if (!Memory::GetPointer(entry_point)) { | 406 | if (!Memory::IsValidVirtualAddress(entry_point)) { |
| 407 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); | 407 | LOG_ERROR(Kernel_SVC, "(name=%s): invalid entry %08x", name.c_str(), entry_point); |
| 408 | // TODO: Verify error | 408 | // TODO: Verify error |
| 409 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, | 409 | return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, |
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp index bbf170b71..1e54a53dd 100644 --- a/src/core/hle/service/apt/apt.cpp +++ b/src/core/hle/service/apt/apt.cpp | |||
| @@ -180,12 +180,12 @@ void SendParameter(Service::Interface* self) { | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | MessageParameter param; | 182 | MessageParameter param; |
| 183 | param.buffer_size = buffer_size; | ||
| 184 | param.destination_id = dst_app_id; | 183 | param.destination_id = dst_app_id; |
| 185 | param.sender_id = src_app_id; | 184 | param.sender_id = src_app_id; |
| 186 | param.object = Kernel::g_handle_table.GetGeneric(handle); | 185 | param.object = Kernel::g_handle_table.GetGeneric(handle); |
| 187 | param.signal = signal_type; | 186 | param.signal = signal_type; |
| 188 | param.data = Memory::GetPointer(buffer); | 187 | param.buffer.resize(buffer_size); |
| 188 | Memory::ReadBlock(buffer, param.buffer.data(), param.buffer.size()); | ||
| 189 | 189 | ||
| 190 | cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; | 190 | cmd_buff[1] = dest_applet->ReceiveParameter(param).raw; |
| 191 | 191 | ||
| @@ -203,16 +203,15 @@ void ReceiveParameter(Service::Interface* self) { | |||
| 203 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 203 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 204 | cmd_buff[2] = next_parameter.sender_id; | 204 | cmd_buff[2] = next_parameter.sender_id; |
| 205 | cmd_buff[3] = next_parameter.signal; // Signal type | 205 | cmd_buff[3] = next_parameter.signal; // Signal type |
| 206 | cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size | 206 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size |
| 207 | cmd_buff[5] = 0x10; | 207 | cmd_buff[5] = 0x10; |
| 208 | cmd_buff[6] = 0; | 208 | cmd_buff[6] = 0; |
| 209 | if (next_parameter.object != nullptr) | 209 | if (next_parameter.object != nullptr) |
| 210 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | 210 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); |
| 211 | cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; | 211 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; |
| 212 | cmd_buff[8] = buffer; | 212 | cmd_buff[8] = buffer; |
| 213 | 213 | ||
| 214 | if (next_parameter.data) | 214 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), next_parameter.buffer.size()); |
| 215 | memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); | ||
| 216 | 215 | ||
| 217 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 216 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 218 | } | 217 | } |
| @@ -226,16 +225,15 @@ void GlanceParameter(Service::Interface* self) { | |||
| 226 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 225 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 227 | cmd_buff[2] = next_parameter.sender_id; | 226 | cmd_buff[2] = next_parameter.sender_id; |
| 228 | cmd_buff[3] = next_parameter.signal; // Signal type | 227 | cmd_buff[3] = next_parameter.signal; // Signal type |
| 229 | cmd_buff[4] = next_parameter.buffer_size; // Parameter buffer size | 228 | cmd_buff[4] = next_parameter.buffer.size(); // Parameter buffer size |
| 230 | cmd_buff[5] = 0x10; | 229 | cmd_buff[5] = 0x10; |
| 231 | cmd_buff[6] = 0; | 230 | cmd_buff[6] = 0; |
| 232 | if (next_parameter.object != nullptr) | 231 | if (next_parameter.object != nullptr) |
| 233 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); | 232 | cmd_buff[6] = Kernel::g_handle_table.Create(next_parameter.object).MoveFrom(); |
| 234 | cmd_buff[7] = (next_parameter.buffer_size << 14) | 2; | 233 | cmd_buff[7] = (next_parameter.buffer.size() << 14) | 2; |
| 235 | cmd_buff[8] = buffer; | 234 | cmd_buff[8] = buffer; |
| 236 | 235 | ||
| 237 | if (next_parameter.data) | 236 | Memory::WriteBlock(buffer, next_parameter.buffer.data(), std::min(static_cast<size_t>(buffer_size), next_parameter.buffer.size())); |
| 238 | memcpy(Memory::GetPointer(buffer), next_parameter.data, std::min(buffer_size, next_parameter.buffer_size)); | ||
| 239 | 237 | ||
| 240 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); | 238 | LOG_WARNING(Service_APT, "called app_id=0x%08X, buffer_size=0x%08X", app_id, buffer_size); |
| 241 | } | 239 | } |
| @@ -373,10 +371,13 @@ void StartLibraryApplet(Service::Interface* self) { | |||
| 373 | return; | 371 | return; |
| 374 | } | 372 | } |
| 375 | 373 | ||
| 374 | size_t buffer_size = cmd_buff[2]; | ||
| 375 | VAddr buffer_addr = cmd_buff[6]; | ||
| 376 | |||
| 376 | AppletStartupParameter parameter; | 377 | AppletStartupParameter parameter; |
| 377 | parameter.buffer_size = cmd_buff[2]; | ||
| 378 | parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); | 378 | parameter.object = Kernel::g_handle_table.GetGeneric(cmd_buff[4]); |
| 379 | parameter.data = Memory::GetPointer(cmd_buff[6]); | 379 | parameter.buffer.resize(buffer_size); |
| 380 | Memory::ReadBlock(buffer_addr, parameter.buffer.data(), parameter.buffer.size()); | ||
| 380 | 381 | ||
| 381 | cmd_buff[1] = applet->Start(parameter).raw; | 382 | cmd_buff[1] = applet->Start(parameter).raw; |
| 382 | } | 383 | } |
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h index ed7c47cca..76b3a3807 100644 --- a/src/core/hle/service/apt/apt.h +++ b/src/core/hle/service/apt/apt.h | |||
| @@ -20,16 +20,14 @@ struct MessageParameter { | |||
| 20 | u32 sender_id = 0; | 20 | u32 sender_id = 0; |
| 21 | u32 destination_id = 0; | 21 | u32 destination_id = 0; |
| 22 | u32 signal = 0; | 22 | u32 signal = 0; |
| 23 | u32 buffer_size = 0; | ||
| 24 | Kernel::SharedPtr<Kernel::Object> object = nullptr; | 23 | Kernel::SharedPtr<Kernel::Object> object = nullptr; |
| 25 | u8* data = nullptr; | 24 | std::vector<u8> buffer; |
| 26 | }; | 25 | }; |
| 27 | 26 | ||
| 28 | /// Holds information about the parameters used in StartLibraryApplet | 27 | /// Holds information about the parameters used in StartLibraryApplet |
| 29 | struct AppletStartupParameter { | 28 | struct AppletStartupParameter { |
| 30 | u32 buffer_size = 0; | ||
| 31 | Kernel::SharedPtr<Kernel::Object> object = nullptr; | 29 | Kernel::SharedPtr<Kernel::Object> object = nullptr; |
| 32 | u8* data = nullptr; | 30 | std::vector<u8> buffer; |
| 33 | }; | 31 | }; |
| 34 | 32 | ||
| 35 | /// Used by the application to pass information about the current framebuffer to applets. | 33 | /// Used by the application to pass information about the current framebuffer to applets. |
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp index acc509cb0..e067db645 100644 --- a/src/core/hle/service/cfg/cfg.cpp +++ b/src/core/hle/service/cfg/cfg.cpp | |||
| @@ -196,28 +196,32 @@ void GetConfigInfoBlk2(Service::Interface* self) { | |||
| 196 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 196 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 197 | u32 size = cmd_buff[1]; | 197 | u32 size = cmd_buff[1]; |
| 198 | u32 block_id = cmd_buff[2]; | 198 | u32 block_id = cmd_buff[2]; |
| 199 | u8* data_pointer = Memory::GetPointer(cmd_buff[4]); | 199 | VAddr data_pointer = cmd_buff[4]; |
| 200 | 200 | ||
| 201 | if (data_pointer == nullptr) { | 201 | if (!Memory::IsValidVirtualAddress(data_pointer)) { |
| 202 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code | 202 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code |
| 203 | return; | 203 | return; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw; | 206 | std::vector<u8> data(size); |
| 207 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw; | ||
| 208 | Memory::WriteBlock(data_pointer, data.data(), data.size()); | ||
| 207 | } | 209 | } |
| 208 | 210 | ||
| 209 | void GetConfigInfoBlk8(Service::Interface* self) { | 211 | void GetConfigInfoBlk8(Service::Interface* self) { |
| 210 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 212 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 211 | u32 size = cmd_buff[1]; | 213 | u32 size = cmd_buff[1]; |
| 212 | u32 block_id = cmd_buff[2]; | 214 | u32 block_id = cmd_buff[2]; |
| 213 | u8* data_pointer = Memory::GetPointer(cmd_buff[4]); | 215 | VAddr data_pointer = cmd_buff[4]; |
| 214 | 216 | ||
| 215 | if (data_pointer == nullptr) { | 217 | if (!Memory::IsValidVirtualAddress(data_pointer)) { |
| 216 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code | 218 | cmd_buff[1] = -1; // TODO(Subv): Find the right error code |
| 217 | return; | 219 | return; |
| 218 | } | 220 | } |
| 219 | 221 | ||
| 220 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data_pointer).raw; | 222 | std::vector<u8> data(size); |
| 223 | cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw; | ||
| 224 | Memory::WriteBlock(data_pointer, data.data(), data.size()); | ||
| 221 | } | 225 | } |
| 222 | 226 | ||
| 223 | void UpdateConfigNANDSavegame(Service::Interface* self) { | 227 | void UpdateConfigNANDSavegame(Service::Interface* self) { |
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 10730d7ac..c8aadd9db 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp | |||
| @@ -140,12 +140,15 @@ static void LoadComponent(Service::Interface* self) { | |||
| 140 | 140 | ||
| 141 | // TODO(bunnei): Implement real DSP firmware loading | 141 | // TODO(bunnei): Implement real DSP firmware loading |
| 142 | 142 | ||
| 143 | ASSERT(Memory::GetPointer(buffer) != nullptr); | 143 | ASSERT(Memory::IsValidVirtualAddress(buffer)); |
| 144 | ASSERT(size > 0x37C); | 144 | |
| 145 | std::vector<u8> component_data(size); | ||
| 146 | Memory::ReadBlock(buffer, component_data.data(), component_data.size()); | ||
| 145 | 147 | ||
| 146 | LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer), size)); | 148 | LOG_INFO(Service_DSP, "Firmware hash: %#" PRIx64, Common::ComputeHash64(component_data.data(), component_data.size())); |
| 147 | // Some versions of the firmware have the location of DSP structures listed here. | 149 | // Some versions of the firmware have the location of DSP structures listed here. |
| 148 | LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(Memory::GetPointer(buffer) + 0x340, 60)); | 150 | ASSERT(size > 0x37C); |
| 151 | LOG_INFO(Service_DSP, "Structures hash: %#" PRIx64, Common::ComputeHash64(component_data.data() + 0x340, 60)); | ||
| 149 | 152 | ||
| 150 | LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", | 153 | LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%X, prog_mask=0x%08X, data_mask=0x%08X, buffer=0x%08X", |
| 151 | size, prog_mask, data_mask, buffer); | 154 | size, prog_mask, data_mask, buffer); |
| @@ -285,7 +288,7 @@ static void WriteProcessPipe(Service::Interface* self) { | |||
| 285 | return; | 288 | return; |
| 286 | } | 289 | } |
| 287 | 290 | ||
| 288 | ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); | 291 | ASSERT_MSG(Memory::IsValidVirtualAddress(buffer), "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); |
| 289 | 292 | ||
| 290 | std::vector<u8> message(size); | 293 | std::vector<u8> message(size); |
| 291 | for (u32 i = 0; i < size; i++) { | 294 | for (u32 i = 0; i < size; i++) { |
| @@ -324,7 +327,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { | |||
| 324 | 327 | ||
| 325 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | 328 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); |
| 326 | 329 | ||
| 327 | ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); | 330 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); |
| 328 | 331 | ||
| 329 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); | 332 | cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); |
| 330 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 333 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| @@ -364,7 +367,7 @@ static void ReadPipe(Service::Interface* self) { | |||
| 364 | 367 | ||
| 365 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); | 368 | DSP::HLE::DspPipe pipe = static_cast<DSP::HLE::DspPipe>(pipe_index); |
| 366 | 369 | ||
| 367 | ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); | 370 | ASSERT_MSG(Memory::IsValidVirtualAddress(addr), "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); |
| 368 | 371 | ||
| 369 | if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { | 372 | if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { |
| 370 | std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); | 373 | std::vector<u8> response = DSP::HLE::PipeRead(pipe, size); |
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp index 15d604bb6..29d144365 100644 --- a/src/core/hle/service/frd/frd.cpp +++ b/src/core/hle/service/frd/frd.cpp | |||
| @@ -23,7 +23,7 @@ void GetMyPresence(Service::Interface* self) { | |||
| 23 | 23 | ||
| 24 | ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); | 24 | ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2)); |
| 25 | 25 | ||
| 26 | Memory::WriteBlock(my_presence_addr, reinterpret_cast<const u8*>(&my_presence), sizeof(MyPresence)); | 26 | Memory::WriteBlock(my_presence_addr, &my_presence, sizeof(MyPresence)); |
| 27 | 27 | ||
| 28 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 28 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 29 | 29 | ||
| @@ -39,8 +39,7 @@ void GetFriendKeyList(Service::Interface* self) { | |||
| 39 | 39 | ||
| 40 | FriendKey zero_key = {}; | 40 | FriendKey zero_key = {}; |
| 41 | for (u32 i = 0; i < frd_count; ++i) { | 41 | for (u32 i = 0; i < frd_count; ++i) { |
| 42 | Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), | 42 | Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey), &zero_key, sizeof(FriendKey)); |
| 43 | reinterpret_cast<const u8*>(&zero_key), sizeof(FriendKey)); | ||
| 44 | } | 43 | } |
| 45 | 44 | ||
| 46 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 45 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| @@ -58,8 +57,7 @@ void GetFriendProfile(Service::Interface* self) { | |||
| 58 | 57 | ||
| 59 | Profile zero_profile = {}; | 58 | Profile zero_profile = {}; |
| 60 | for (u32 i = 0; i < count; ++i) { | 59 | for (u32 i = 0; i < count; ++i) { |
| 61 | Memory::WriteBlock(profiles_addr + i * sizeof(Profile), | 60 | Memory::WriteBlock(profiles_addr + i * sizeof(Profile), &zero_profile, sizeof(Profile)); |
| 62 | reinterpret_cast<const u8*>(&zero_profile), sizeof(Profile)); | ||
| 63 | } | 61 | } |
| 64 | 62 | ||
| 65 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 63 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| @@ -88,7 +86,7 @@ void GetMyFriendKey(Service::Interface* self) { | |||
| 88 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 86 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 89 | 87 | ||
| 90 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error | 88 | cmd_buff[1] = RESULT_SUCCESS.raw; // No error |
| 91 | Memory::WriteBlock(cmd_buff[2], reinterpret_cast<const u8*>(&my_friend_key), sizeof(FriendKey)); | 89 | Memory::WriteBlock(cmd_buff[2], &my_friend_key, sizeof(FriendKey)); |
| 92 | LOG_WARNING(Service_FRD, "(STUBBED) called"); | 90 | LOG_WARNING(Service_FRD, "(STUBBED) called"); |
| 93 | } | 91 | } |
| 94 | 92 | ||
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp index cc51ede0c..81b9abe4c 100644 --- a/src/core/hle/service/fs/archive.cpp +++ b/src/core/hle/service/fs/archive.cpp | |||
| @@ -108,13 +108,14 @@ ResultVal<bool> File::SyncRequest() { | |||
| 108 | offset, length, backend->GetSize()); | 108 | offset, length, backend->GetSize()); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | ResultVal<size_t> read = backend->Read(offset, length, Memory::GetPointer(address)); | 111 | std::vector<u8> data(length); |
| 112 | ResultVal<size_t> read = backend->Read(offset, data.size(), data.data()); | ||
| 112 | if (read.Failed()) { | 113 | if (read.Failed()) { |
| 113 | cmd_buff[1] = read.Code().raw; | 114 | cmd_buff[1] = read.Code().raw; |
| 114 | return read.Code(); | 115 | return read.Code(); |
| 115 | } | 116 | } |
| 117 | Memory::WriteBlock(address, data.data(), *read); | ||
| 116 | cmd_buff[2] = static_cast<u32>(*read); | 118 | cmd_buff[2] = static_cast<u32>(*read); |
| 117 | Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(address), length); | ||
| 118 | break; | 119 | break; |
| 119 | } | 120 | } |
| 120 | 121 | ||
| @@ -128,7 +129,9 @@ ResultVal<bool> File::SyncRequest() { | |||
| 128 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", | 129 | LOG_TRACE(Service_FS, "Write %s %s: offset=0x%llx length=%d address=0x%x, flush=0x%x", |
| 129 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); | 130 | GetTypeName().c_str(), GetName().c_str(), offset, length, address, flush); |
| 130 | 131 | ||
| 131 | ResultVal<size_t> written = backend->Write(offset, length, flush != 0, Memory::GetPointer(address)); | 132 | std::vector<u8> data(length); |
| 133 | Memory::ReadBlock(address, data.data(), data.size()); | ||
| 134 | ResultVal<size_t> written = backend->Write(offset, data.size(), flush != 0, data.data()); | ||
| 132 | if (written.Failed()) { | 135 | if (written.Failed()) { |
| 133 | cmd_buff[1] = written.Code().raw; | 136 | cmd_buff[1] = written.Code().raw; |
| 134 | return written.Code(); | 137 | return written.Code(); |
| @@ -216,12 +219,14 @@ ResultVal<bool> Directory::SyncRequest() { | |||
| 216 | { | 219 | { |
| 217 | u32 count = cmd_buff[1]; | 220 | u32 count = cmd_buff[1]; |
| 218 | u32 address = cmd_buff[3]; | 221 | u32 address = cmd_buff[3]; |
| 219 | auto entries = reinterpret_cast<FileSys::Entry*>(Memory::GetPointer(address)); | 222 | std::vector<FileSys::Entry> entries(count); |
| 220 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", | 223 | LOG_TRACE(Service_FS, "Read %s %s: count=%d", |
| 221 | GetTypeName().c_str(), GetName().c_str(), count); | 224 | GetTypeName().c_str(), GetName().c_str(), count); |
| 222 | 225 | ||
| 223 | // Number of entries actually read | 226 | // Number of entries actually read |
| 224 | cmd_buff[2] = backend->Read(count, entries); | 227 | u32 read = backend->Read(entries.size(), entries.data()); |
| 228 | cmd_buff[2] = read; | ||
| 229 | Memory::WriteBlock(address, entries.data(), read * sizeof(FileSys::Entry)); | ||
| 225 | break; | 230 | break; |
| 226 | } | 231 | } |
| 227 | 232 | ||
| @@ -456,11 +461,12 @@ ResultCode CreateExtSaveData(MediaType media_type, u32 high, u32 low, VAddr icon | |||
| 456 | if (result.IsError()) | 461 | if (result.IsError()) |
| 457 | return result; | 462 | return result; |
| 458 | 463 | ||
| 459 | u8* smdh_icon = Memory::GetPointer(icon_buffer); | 464 | if (!Memory::IsValidVirtualAddress(icon_buffer)) |
| 460 | if (!smdh_icon) | ||
| 461 | return ResultCode(-1); // TODO(Subv): Find the right error code | 465 | return ResultCode(-1); // TODO(Subv): Find the right error code |
| 462 | 466 | ||
| 463 | ext_savedata->WriteIcon(path, smdh_icon, icon_size); | 467 | std::vector<u8> smdh_icon(icon_size); |
| 468 | Memory::ReadBlock(icon_buffer, smdh_icon.data(), smdh_icon.size()); | ||
| 469 | ext_savedata->WriteIcon(path, smdh_icon.data(), smdh_icon.size()); | ||
| 464 | return RESULT_SUCCESS; | 470 | return RESULT_SUCCESS; |
| 465 | } | 471 | } |
| 466 | 472 | ||
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp index 8ded9b09b..f3c7b7df3 100644 --- a/src/core/hle/service/gsp_gpu.cpp +++ b/src/core/hle/service/gsp_gpu.cpp | |||
| @@ -66,14 +66,26 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | |||
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | /** | 68 | /** |
| 69 | * Writes a single GSP GPU hardware registers with a single u32 value | ||
| 70 | * (For internal use.) | ||
| 71 | * | ||
| 72 | * @param base_address The address of the register in question | ||
| 73 | * @param data Data to be written | ||
| 74 | */ | ||
| 75 | static void WriteSingleHWReg(u32 base_address, u32 data) { | ||
| 76 | DEBUG_ASSERT_MSG((base_address & 3) == 0 && base_address < 0x420000, "Write address out of range or misaligned"); | ||
| 77 | HW::Write<u32>(base_address + REGS_BEGIN, data); | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 69 | * Writes sequential GSP GPU hardware registers using an array of source data | 81 | * Writes sequential GSP GPU hardware registers using an array of source data |
| 70 | * | 82 | * |
| 71 | * @param base_address The address of the first register in the sequence | 83 | * @param base_address The address of the first register in the sequence |
| 72 | * @param size_in_bytes The number of registers to update (size of data) | 84 | * @param size_in_bytes The number of registers to update (size of data) |
| 73 | * @param data A pointer to the source data | 85 | * @param data_vaddr A pointer to the source data |
| 74 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise | 86 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise |
| 75 | */ | 87 | */ |
| 76 | static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { | 88 | static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, VAddr data_vaddr) { |
| 77 | // This magic number is verified to be done by the gsp module | 89 | // This magic number is verified to be done by the gsp module |
| 78 | const u32 max_size_in_bytes = 0x80; | 90 | const u32 max_size_in_bytes = 0x80; |
| 79 | 91 | ||
| @@ -87,10 +99,10 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da | |||
| 87 | return ERR_GSP_REGS_MISALIGNED; | 99 | return ERR_GSP_REGS_MISALIGNED; |
| 88 | } else { | 100 | } else { |
| 89 | while (size_in_bytes > 0) { | 101 | while (size_in_bytes > 0) { |
| 90 | HW::Write<u32>(base_address + REGS_BEGIN, *data); | 102 | WriteSingleHWReg(base_address, Memory::Read32(data_vaddr)); |
| 91 | 103 | ||
| 92 | size_in_bytes -= 4; | 104 | size_in_bytes -= 4; |
| 93 | ++data; | 105 | data_vaddr += 4; |
| 94 | base_address += 4; | 106 | base_address += 4; |
| 95 | } | 107 | } |
| 96 | return RESULT_SUCCESS; | 108 | return RESULT_SUCCESS; |
| @@ -112,7 +124,7 @@ static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* da | |||
| 112 | * @param masks A pointer to the masks | 124 | * @param masks A pointer to the masks |
| 113 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise | 125 | * @return RESULT_SUCCESS if the parameters are valid, error code otherwise |
| 114 | */ | 126 | */ |
| 115 | static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) { | 127 | static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, VAddr data_vaddr, VAddr masks_vaddr) { |
| 116 | // This magic number is verified to be done by the gsp module | 128 | // This magic number is verified to be done by the gsp module |
| 117 | const u32 max_size_in_bytes = 0x80; | 129 | const u32 max_size_in_bytes = 0x80; |
| 118 | 130 | ||
| @@ -131,14 +143,17 @@ static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const | |||
| 131 | u32 reg_value; | 143 | u32 reg_value; |
| 132 | HW::Read<u32>(reg_value, reg_address); | 144 | HW::Read<u32>(reg_value, reg_address); |
| 133 | 145 | ||
| 146 | u32 data = Memory::Read32(data_vaddr); | ||
| 147 | u32 mask = Memory::Read32(masks_vaddr); | ||
| 148 | |||
| 134 | // Update the current value of the register only for set mask bits | 149 | // Update the current value of the register only for set mask bits |
| 135 | reg_value = (reg_value & ~*masks) | (*data | *masks); | 150 | reg_value = (reg_value & ~mask) | (data | mask); |
| 136 | 151 | ||
| 137 | HW::Write<u32>(reg_address, reg_value); | 152 | WriteSingleHWReg(base_address, reg_value); |
| 138 | 153 | ||
| 139 | size_in_bytes -= 4; | 154 | size_in_bytes -= 4; |
| 140 | ++data; | 155 | data_vaddr += 4; |
| 141 | ++masks; | 156 | masks_vaddr += 4; |
| 142 | base_address += 4; | 157 | base_address += 4; |
| 143 | } | 158 | } |
| 144 | return RESULT_SUCCESS; | 159 | return RESULT_SUCCESS; |
| @@ -164,8 +179,7 @@ static void WriteHWRegs(Service::Interface* self) { | |||
| 164 | u32* cmd_buff = Kernel::GetCommandBuffer(); | 179 | u32* cmd_buff = Kernel::GetCommandBuffer(); |
| 165 | u32 reg_addr = cmd_buff[1]; | 180 | u32 reg_addr = cmd_buff[1]; |
| 166 | u32 size = cmd_buff[2]; | 181 | u32 size = cmd_buff[2]; |
| 167 | 182 | VAddr src = cmd_buff[4]; | |
| 168 | u32* src = (u32*)Memory::GetPointer(cmd_buff[4]); | ||
| 169 | 183 | ||
| 170 | cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; | 184 | cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw; |
| 171 | } | 185 | } |
| @@ -186,8 +200,8 @@ static void WriteHWRegsWithMask(Service::Interface* self) { | |||
| 186 | u32 reg_addr = cmd_buff[1]; | 200 | u32 reg_addr = cmd_buff[1]; |
| 187 | u32 size = cmd_buff[2]; | 201 | u32 size = cmd_buff[2]; |
| 188 | 202 | ||
| 189 | u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]); | 203 | VAddr src_data = cmd_buff[4]; |
| 190 | u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]); | 204 | VAddr mask_data = cmd_buff[6]; |
| 191 | 205 | ||
| 192 | cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; | 206 | cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw; |
| 193 | } | 207 | } |
| @@ -210,13 +224,16 @@ static void ReadHWRegs(Service::Interface* self) { | |||
| 210 | return; | 224 | return; |
| 211 | } | 225 | } |
| 212 | 226 | ||
| 213 | u32* dst = (u32*)Memory::GetPointer(cmd_buff[0x41]); | 227 | VAddr dst_vaddr = cmd_buff[0x41]; |
| 214 | 228 | ||
| 215 | while (size > 0) { | 229 | while (size > 0) { |
| 216 | HW::Read<u32>(*dst, reg_addr + REGS_BEGIN); | 230 | u32 value; |
| 231 | HW::Read<u32>(value, reg_addr + REGS_BEGIN); | ||
| 232 | |||
| 233 | Memory::Write32(dst_vaddr, value); | ||
| 217 | 234 | ||
| 218 | size -= 4; | 235 | size -= 4; |
| 219 | ++dst; | 236 | dst_vaddr += 4; |
| 220 | reg_addr += 4; | 237 | reg_addr += 4; |
| 221 | } | 238 | } |
| 222 | } | 239 | } |
| @@ -226,22 +243,22 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { | |||
| 226 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); | 243 | PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left); |
| 227 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); | 244 | PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right); |
| 228 | if (info.active_fb == 0) { | 245 | if (info.active_fb == 0) { |
| 229 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), | 246 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), |
| 230 | 4, &phys_address_left); | 247 | phys_address_left); |
| 231 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), | 248 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), |
| 232 | 4, &phys_address_right); | 249 | phys_address_right); |
| 233 | } else { | 250 | } else { |
| 234 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), | 251 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), |
| 235 | 4, &phys_address_left); | 252 | phys_address_left); |
| 236 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), | 253 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), |
| 237 | 4, &phys_address_right); | 254 | phys_address_right); |
| 238 | } | 255 | } |
| 239 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), | 256 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), |
| 240 | 4, &info.stride); | 257 | info.stride); |
| 241 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), | 258 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), |
| 242 | 4, &info.format); | 259 | info.format); |
| 243 | WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), | 260 | WriteSingleHWReg(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), |
| 244 | 4, &info.shown_fb); | 261 | info.shown_fb); |
| 245 | 262 | ||
| 246 | if (Pica::g_debug_context) | 263 | if (Pica::g_debug_context) |
| 247 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); | 264 | Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr); |
| @@ -432,9 +449,9 @@ static void ExecuteCommand(const Command& command, u32 thread_id) { | |||
| 432 | Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), | 449 | Memory::RasterizerFlushAndInvalidateRegion(Memory::VirtualToPhysicalAddress(command.dma_request.dest_address), |
| 433 | command.dma_request.size); | 450 | command.dma_request.size); |
| 434 | 451 | ||
| 435 | memcpy(Memory::GetPointer(command.dma_request.dest_address), | 452 | // TODO(Subv): These memory accesses should not go through the application's memory mapping. |
| 436 | Memory::GetPointer(command.dma_request.source_address), | 453 | // They should go through the GSP module's memory mapping. |
| 437 | command.dma_request.size); | 454 | Memory::CopyBlock(command.dma_request.dest_address, command.dma_request.source_address, command.dma_request.size); |
| 438 | SignalInterrupt(InterruptId::DMA); | 455 | SignalInterrupt(InterruptId::DMA); |
| 439 | break; | 456 | break; |
| 440 | } | 457 | } |
diff --git a/src/core/hle/service/soc_u.cpp b/src/core/hle/service/soc_u.cpp index d3e5d4bca..9b285567b 100644 --- a/src/core/hle/service/soc_u.cpp +++ b/src/core/hle/service/soc_u.cpp | |||
| @@ -373,14 +373,18 @@ static void Bind(Service::Interface* self) { | |||
| 373 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 373 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 374 | u32 socket_handle = cmd_buffer[1]; | 374 | u32 socket_handle = cmd_buffer[1]; |
| 375 | u32 len = cmd_buffer[2]; | 375 | u32 len = cmd_buffer[2]; |
| 376 | CTRSockAddr* ctr_sock_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6])); | ||
| 377 | 376 | ||
| 378 | if (ctr_sock_addr == nullptr) { | 377 | // Virtual address of the sock_addr structure |
| 378 | VAddr sock_addr_addr = cmd_buffer[6]; | ||
| 379 | if (!Memory::IsValidVirtualAddress(sock_addr_addr)) { | ||
| 379 | cmd_buffer[1] = -1; // TODO(Subv): Correct code | 380 | cmd_buffer[1] = -1; // TODO(Subv): Correct code |
| 380 | return; | 381 | return; |
| 381 | } | 382 | } |
| 382 | 383 | ||
| 383 | sockaddr sock_addr = CTRSockAddr::ToPlatform(*ctr_sock_addr); | 384 | CTRSockAddr ctr_sock_addr; |
| 385 | Memory::ReadBlock(sock_addr_addr, reinterpret_cast<u8*>(&ctr_sock_addr), sizeof(CTRSockAddr)); | ||
| 386 | |||
| 387 | sockaddr sock_addr = CTRSockAddr::ToPlatform(ctr_sock_addr); | ||
| 384 | 388 | ||
| 385 | int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); | 389 | int res = ::bind(socket_handle, &sock_addr, std::max<u32>(sizeof(sock_addr), len)); |
| 386 | 390 | ||
| @@ -496,7 +500,7 @@ static void Accept(Service::Interface* self) { | |||
| 496 | result = TranslateError(GET_ERRNO); | 500 | result = TranslateError(GET_ERRNO); |
| 497 | } else { | 501 | } else { |
| 498 | CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); | 502 | CTRSockAddr ctr_addr = CTRSockAddr::FromPlatform(addr); |
| 499 | Memory::WriteBlock(cmd_buffer[0x104 >> 2], (const u8*)&ctr_addr, max_addr_len); | 503 | Memory::WriteBlock(cmd_buffer[0x104 >> 2], &ctr_addr, sizeof(ctr_addr)); |
| 500 | } | 504 | } |
| 501 | 505 | ||
| 502 | cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); | 506 | cmd_buffer[0] = IPC::MakeHeader(4, 2, 2); |
| @@ -547,20 +551,31 @@ static void SendTo(Service::Interface* self) { | |||
| 547 | u32 flags = cmd_buffer[3]; | 551 | u32 flags = cmd_buffer[3]; |
| 548 | u32 addr_len = cmd_buffer[4]; | 552 | u32 addr_len = cmd_buffer[4]; |
| 549 | 553 | ||
| 550 | u8* input_buff = Memory::GetPointer(cmd_buffer[8]); | 554 | VAddr input_buff_address = cmd_buffer[8]; |
| 551 | CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[10])); | 555 | if (!Memory::IsValidVirtualAddress(input_buff_address)) { |
| 556 | cmd_buffer[1] = -1; // TODO(Subv): Find the right error code | ||
| 557 | return; | ||
| 558 | } | ||
| 552 | 559 | ||
| 553 | if (ctr_dest_addr == nullptr) { | 560 | // Memory address of the dest_addr structure |
| 561 | VAddr dest_addr_addr = cmd_buffer[10]; | ||
| 562 | if (!Memory::IsValidVirtualAddress(dest_addr_addr)) { | ||
| 554 | cmd_buffer[1] = -1; // TODO(Subv): Find the right error code | 563 | cmd_buffer[1] = -1; // TODO(Subv): Find the right error code |
| 555 | return; | 564 | return; |
| 556 | } | 565 | } |
| 557 | 566 | ||
| 567 | std::vector<u8> input_buff(len); | ||
| 568 | Memory::ReadBlock(input_buff_address, input_buff.data(), input_buff.size()); | ||
| 569 | |||
| 570 | CTRSockAddr ctr_dest_addr; | ||
| 571 | Memory::ReadBlock(dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||
| 572 | |||
| 558 | int ret = -1; | 573 | int ret = -1; |
| 559 | if (addr_len > 0) { | 574 | if (addr_len > 0) { |
| 560 | sockaddr dest_addr = CTRSockAddr::ToPlatform(*ctr_dest_addr); | 575 | sockaddr dest_addr = CTRSockAddr::ToPlatform(ctr_dest_addr); |
| 561 | ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, &dest_addr, sizeof(dest_addr)); | 576 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, &dest_addr, sizeof(dest_addr)); |
| 562 | } else { | 577 | } else { |
| 563 | ret = ::sendto(socket_handle, (const char*)input_buff, len, flags, nullptr, 0); | 578 | ret = ::sendto(socket_handle, reinterpret_cast<const char*>(input_buff.data()), len, flags, nullptr, 0); |
| 564 | } | 579 | } |
| 565 | 580 | ||
| 566 | int result = 0; | 581 | int result = 0; |
| @@ -591,14 +606,24 @@ static void RecvFrom(Service::Interface* self) { | |||
| 591 | 606 | ||
| 592 | std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); | 607 | std::memcpy(&buffer_parameters, &cmd_buffer[64], sizeof(buffer_parameters)); |
| 593 | 608 | ||
| 594 | u8* output_buff = Memory::GetPointer(buffer_parameters.output_buffer_addr); | 609 | if (!Memory::IsValidVirtualAddress(buffer_parameters.output_buffer_addr)) { |
| 610 | cmd_buffer[1] = -1; // TODO(Subv): Find the right error code | ||
| 611 | return; | ||
| 612 | } | ||
| 613 | |||
| 614 | if (!Memory::IsValidVirtualAddress(buffer_parameters.output_src_address_buffer)) { | ||
| 615 | cmd_buffer[1] = -1; // TODO(Subv): Find the right error code | ||
| 616 | return; | ||
| 617 | } | ||
| 618 | |||
| 619 | std::vector<u8> output_buff(len); | ||
| 595 | sockaddr src_addr; | 620 | sockaddr src_addr; |
| 596 | socklen_t src_addr_len = sizeof(src_addr); | 621 | socklen_t src_addr_len = sizeof(src_addr); |
| 597 | int ret = ::recvfrom(socket_handle, (char*)output_buff, len, flags, &src_addr, &src_addr_len); | 622 | int ret = ::recvfrom(socket_handle, reinterpret_cast<char*>(output_buff.data()), len, flags, &src_addr, &src_addr_len); |
| 598 | 623 | ||
| 599 | if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { | 624 | if (ret >= 0 && buffer_parameters.output_src_address_buffer != 0 && src_addr_len > 0) { |
| 600 | CTRSockAddr* ctr_src_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(buffer_parameters.output_src_address_buffer)); | 625 | CTRSockAddr ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); |
| 601 | *ctr_src_addr = CTRSockAddr::FromPlatform(src_addr); | 626 | Memory::WriteBlock(buffer_parameters.output_src_address_buffer, &ctr_src_addr, sizeof(ctr_src_addr)); |
| 602 | } | 627 | } |
| 603 | 628 | ||
| 604 | int result = 0; | 629 | int result = 0; |
| @@ -606,6 +631,9 @@ static void RecvFrom(Service::Interface* self) { | |||
| 606 | if (ret == SOCKET_ERROR_VALUE) { | 631 | if (ret == SOCKET_ERROR_VALUE) { |
| 607 | result = TranslateError(GET_ERRNO); | 632 | result = TranslateError(GET_ERRNO); |
| 608 | total_received = 0; | 633 | total_received = 0; |
| 634 | } else { | ||
| 635 | // Write only the data we received to avoid overwriting parts of the buffer with zeros | ||
| 636 | Memory::WriteBlock(buffer_parameters.output_buffer_addr, output_buff.data(), total_received); | ||
| 609 | } | 637 | } |
| 610 | 638 | ||
| 611 | cmd_buffer[1] = result; | 639 | cmd_buffer[1] = result; |
| @@ -617,18 +645,28 @@ static void Poll(Service::Interface* self) { | |||
| 617 | u32* cmd_buffer = Kernel::GetCommandBuffer(); | 645 | u32* cmd_buffer = Kernel::GetCommandBuffer(); |
| 618 | u32 nfds = cmd_buffer[1]; | 646 | u32 nfds = cmd_buffer[1]; |
| 619 | int timeout = cmd_buffer[2]; | 647 | int timeout = cmd_buffer[2]; |
| 620 | CTRPollFD* input_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[6])); | 648 | |
| 621 | CTRPollFD* output_fds = reinterpret_cast<CTRPollFD*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | 649 | VAddr input_fds_addr = cmd_buffer[6]; |
| 650 | VAddr output_fds_addr = cmd_buffer[0x104 >> 2]; | ||
| 651 | if (!Memory::IsValidVirtualAddress(input_fds_addr) || !Memory::IsValidVirtualAddress(output_fds_addr)) { | ||
| 652 | cmd_buffer[1] = -1; // TODO(Subv): Find correct error code. | ||
| 653 | return; | ||
| 654 | } | ||
| 655 | |||
| 656 | std::vector<CTRPollFD> ctr_fds(nfds); | ||
| 657 | Memory::ReadBlock(input_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | ||
| 622 | 658 | ||
| 623 | // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) | 659 | // The 3ds_pollfd and the pollfd structures may be different (Windows/Linux have different sizes) |
| 624 | // so we have to copy the data | 660 | // so we have to copy the data |
| 625 | std::vector<pollfd> platform_pollfd(nfds); | 661 | std::vector<pollfd> platform_pollfd(nfds); |
| 626 | std::transform(input_fds, input_fds + nfds, platform_pollfd.begin(), CTRPollFD::ToPlatform); | 662 | std::transform(ctr_fds.begin(), ctr_fds.end(), platform_pollfd.begin(), CTRPollFD::ToPlatform); |
| 627 | 663 | ||
| 628 | const int ret = ::poll(platform_pollfd.data(), nfds, timeout); | 664 | const int ret = ::poll(platform_pollfd.data(), nfds, timeout); |
| 629 | 665 | ||
| 630 | // Now update the output pollfd structure | 666 | // Now update the output pollfd structure |
| 631 | std::transform(platform_pollfd.begin(), platform_pollfd.end(), output_fds, CTRPollFD::FromPlatform); | 667 | std::transform(platform_pollfd.begin(), platform_pollfd.end(), ctr_fds.begin(), CTRPollFD::FromPlatform); |
| 668 | |||
| 669 | Memory::WriteBlock(output_fds_addr, ctr_fds.data(), nfds * sizeof(CTRPollFD)); | ||
| 632 | 670 | ||
| 633 | int result = 0; | 671 | int result = 0; |
| 634 | if (ret == SOCKET_ERROR_VALUE) | 672 | if (ret == SOCKET_ERROR_VALUE) |
| @@ -643,14 +681,16 @@ static void GetSockName(Service::Interface* self) { | |||
| 643 | u32 socket_handle = cmd_buffer[1]; | 681 | u32 socket_handle = cmd_buffer[1]; |
| 644 | socklen_t ctr_len = cmd_buffer[2]; | 682 | socklen_t ctr_len = cmd_buffer[2]; |
| 645 | 683 | ||
| 646 | CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | 684 | // Memory address of the ctr_dest_addr structure |
| 685 | VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; | ||
| 647 | 686 | ||
| 648 | sockaddr dest_addr; | 687 | sockaddr dest_addr; |
| 649 | socklen_t dest_addr_len = sizeof(dest_addr); | 688 | socklen_t dest_addr_len = sizeof(dest_addr); |
| 650 | int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); | 689 | int ret = ::getsockname(socket_handle, &dest_addr, &dest_addr_len); |
| 651 | 690 | ||
| 652 | if (ctr_dest_addr != nullptr) { | 691 | if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { |
| 653 | *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | 692 | CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); |
| 693 | Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||
| 654 | } else { | 694 | } else { |
| 655 | cmd_buffer[1] = -1; // TODO(Subv): Verify error | 695 | cmd_buffer[1] = -1; // TODO(Subv): Verify error |
| 656 | return; | 696 | return; |
| @@ -682,14 +722,16 @@ static void GetPeerName(Service::Interface* self) { | |||
| 682 | u32 socket_handle = cmd_buffer[1]; | 722 | u32 socket_handle = cmd_buffer[1]; |
| 683 | socklen_t len = cmd_buffer[2]; | 723 | socklen_t len = cmd_buffer[2]; |
| 684 | 724 | ||
| 685 | CTRSockAddr* ctr_dest_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[0x104 >> 2])); | 725 | // Memory address of the ctr_dest_addr structure |
| 726 | VAddr ctr_dest_addr_addr = cmd_buffer[0x104 >> 2]; | ||
| 686 | 727 | ||
| 687 | sockaddr dest_addr; | 728 | sockaddr dest_addr; |
| 688 | socklen_t dest_addr_len = sizeof(dest_addr); | 729 | socklen_t dest_addr_len = sizeof(dest_addr); |
| 689 | int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); | 730 | int ret = ::getpeername(socket_handle, &dest_addr, &dest_addr_len); |
| 690 | 731 | ||
| 691 | if (ctr_dest_addr != nullptr) { | 732 | if (ctr_dest_addr_addr != 0 && Memory::IsValidVirtualAddress(ctr_dest_addr_addr)) { |
| 692 | *ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); | 733 | CTRSockAddr ctr_dest_addr = CTRSockAddr::FromPlatform(dest_addr); |
| 734 | Memory::WriteBlock(ctr_dest_addr_addr, &ctr_dest_addr, sizeof(ctr_dest_addr)); | ||
| 693 | } else { | 735 | } else { |
| 694 | cmd_buffer[1] = -1; | 736 | cmd_buffer[1] = -1; |
| 695 | return; | 737 | return; |
| @@ -711,13 +753,17 @@ static void Connect(Service::Interface* self) { | |||
| 711 | u32 socket_handle = cmd_buffer[1]; | 753 | u32 socket_handle = cmd_buffer[1]; |
| 712 | socklen_t len = cmd_buffer[2]; | 754 | socklen_t len = cmd_buffer[2]; |
| 713 | 755 | ||
| 714 | CTRSockAddr* ctr_input_addr = reinterpret_cast<CTRSockAddr*>(Memory::GetPointer(cmd_buffer[6])); | 756 | // Memory address of the ctr_input_addr structure |
| 715 | if (ctr_input_addr == nullptr) { | 757 | VAddr ctr_input_addr_addr = cmd_buffer[6]; |
| 758 | if (!Memory::IsValidVirtualAddress(ctr_input_addr_addr)) { | ||
| 716 | cmd_buffer[1] = -1; // TODO(Subv): Verify error | 759 | cmd_buffer[1] = -1; // TODO(Subv): Verify error |
| 717 | return; | 760 | return; |
| 718 | } | 761 | } |
| 719 | 762 | ||
| 720 | sockaddr input_addr = CTRSockAddr::ToPlatform(*ctr_input_addr); | 763 | CTRSockAddr ctr_input_addr; |
| 764 | Memory::ReadBlock(ctr_input_addr_addr, &ctr_input_addr, sizeof(ctr_input_addr)); | ||
| 765 | |||
| 766 | sockaddr input_addr = CTRSockAddr::ToPlatform(ctr_input_addr); | ||
| 721 | int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); | 767 | int ret = ::connect(socket_handle, &input_addr, sizeof(input_addr)); |
| 722 | int result = 0; | 768 | int result = 0; |
| 723 | if (ret != 0) | 769 | if (ret != 0) |
diff --git a/src/core/hle/service/ssl_c.cpp b/src/core/hle/service/ssl_c.cpp index 14a4e98ec..a8aff1abf 100644 --- a/src/core/hle/service/ssl_c.cpp +++ b/src/core/hle/service/ssl_c.cpp | |||
| @@ -31,7 +31,6 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 31 | 31 | ||
| 32 | u32 size = cmd_buff[1]; | 32 | u32 size = cmd_buff[1]; |
| 33 | VAddr address = cmd_buff[3]; | 33 | VAddr address = cmd_buff[3]; |
| 34 | u8* output_buff = Memory::GetPointer(address); | ||
| 35 | 34 | ||
| 36 | // Fill the output buffer with random data. | 35 | // Fill the output buffer with random data. |
| 37 | u32 data = 0; | 36 | u32 data = 0; |
| @@ -44,13 +43,13 @@ static void GenerateRandomData(Service::Interface* self) { | |||
| 44 | 43 | ||
| 45 | if (size > 4) { | 44 | if (size > 4) { |
| 46 | // Use up the entire 4 bytes of the random data for as long as possible | 45 | // Use up the entire 4 bytes of the random data for as long as possible |
| 47 | *(u32*)(output_buff + i) = data; | 46 | Memory::Write32(address + i, data); |
| 48 | i += 4; | 47 | i += 4; |
| 49 | } else if (size == 2) { | 48 | } else if (size == 2) { |
| 50 | *(u16*)(output_buff + i) = (u16)(data & 0xffff); | 49 | Memory::Write16(address + i, static_cast<u16>(data & 0xffff)); |
| 51 | i += 2; | 50 | i += 2; |
| 52 | } else { | 51 | } else { |
| 53 | *(u8*)(output_buff + i) = (u8)(data & 0xff); | 52 | Memory::Write8(address + i, static_cast<u8>(data & 0xff)); |
| 54 | i++; | 53 | i++; |
| 55 | } | 54 | } |
| 56 | } | 55 | } |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index ee9b69f81..8c9e5d46d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -246,6 +246,26 @@ void Write(const VAddr vaddr, const T data) { | |||
| 246 | } | 246 | } |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | bool IsValidVirtualAddress(const VAddr vaddr) { | ||
| 250 | const u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 251 | if (page_pointer) | ||
| 252 | return true; | ||
| 253 | |||
| 254 | if (current_page_table->attributes[vaddr >> PAGE_BITS] != PageType::Special) | ||
| 255 | return false; | ||
| 256 | |||
| 257 | MMIORegionPointer mmio_region = GetMMIOHandler(vaddr); | ||
| 258 | if (mmio_region) { | ||
| 259 | return mmio_region->IsValidAddress(vaddr); | ||
| 260 | } | ||
| 261 | |||
| 262 | return false; | ||
| 263 | } | ||
| 264 | |||
| 265 | bool IsValidPhysicalAddress(const PAddr paddr) { | ||
| 266 | return IsValidVirtualAddress(PhysicalToVirtualAddress(paddr)); | ||
| 267 | } | ||
| 268 | |||
| 249 | u8* GetPointer(const VAddr vaddr) { | 269 | u8* GetPointer(const VAddr vaddr) { |
| 250 | u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 270 | u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; |
| 251 | if (page_pointer) { | 271 | if (page_pointer) { |
| @@ -261,6 +281,7 @@ u8* GetPointer(const VAddr vaddr) { | |||
| 261 | } | 281 | } |
| 262 | 282 | ||
| 263 | u8* GetPhysicalPointer(PAddr address) { | 283 | u8* GetPhysicalPointer(PAddr address) { |
| 284 | // TODO(Subv): This call should not go through the application's memory mapping. | ||
| 264 | return GetPointer(PhysicalToVirtualAddress(address)); | 285 | return GetPointer(PhysicalToVirtualAddress(address)); |
| 265 | } | 286 | } |
| 266 | 287 | ||
| @@ -343,6 +364,59 @@ u64 Read64(const VAddr addr) { | |||
| 343 | return Read<u64_le>(addr); | 364 | return Read<u64_le>(addr); |
| 344 | } | 365 | } |
| 345 | 366 | ||
| 367 | void ReadBlock(const VAddr src_addr, void* dest_buffer, const size_t size) { | ||
| 368 | size_t remaining_size = size; | ||
| 369 | size_t page_index = src_addr >> PAGE_BITS; | ||
| 370 | size_t page_offset = src_addr & PAGE_MASK; | ||
| 371 | |||
| 372 | while (remaining_size > 0) { | ||
| 373 | const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||
| 374 | const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||
| 375 | |||
| 376 | switch (current_page_table->attributes[page_index]) { | ||
| 377 | case PageType::Unmapped: { | ||
| 378 | LOG_ERROR(HW_Memory, "unmapped ReadBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | ||
| 379 | std::memset(dest_buffer, 0, copy_amount); | ||
| 380 | break; | ||
| 381 | } | ||
| 382 | case PageType::Memory: { | ||
| 383 | DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||
| 384 | |||
| 385 | const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; | ||
| 386 | std::memcpy(dest_buffer, src_ptr, copy_amount); | ||
| 387 | break; | ||
| 388 | } | ||
| 389 | case PageType::Special: { | ||
| 390 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 391 | |||
| 392 | GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||
| 393 | break; | ||
| 394 | } | ||
| 395 | case PageType::RasterizerCachedMemory: { | ||
| 396 | RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 397 | |||
| 398 | std::memcpy(dest_buffer, GetPointerFromVMA(current_vaddr), copy_amount); | ||
| 399 | break; | ||
| 400 | } | ||
| 401 | case PageType::RasterizerCachedSpecial: { | ||
| 402 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 403 | |||
| 404 | RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 405 | |||
| 406 | GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, dest_buffer, copy_amount); | ||
| 407 | break; | ||
| 408 | } | ||
| 409 | default: | ||
| 410 | UNREACHABLE(); | ||
| 411 | } | ||
| 412 | |||
| 413 | page_index++; | ||
| 414 | page_offset = 0; | ||
| 415 | dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount; | ||
| 416 | remaining_size -= copy_amount; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | |||
| 346 | void Write8(const VAddr addr, const u8 data) { | 420 | void Write8(const VAddr addr, const u8 data) { |
| 347 | Write<u8>(addr, data); | 421 | Write<u8>(addr, data); |
| 348 | } | 422 | } |
| @@ -359,9 +433,165 @@ void Write64(const VAddr addr, const u64 data) { | |||
| 359 | Write<u64_le>(addr, data); | 433 | Write<u64_le>(addr, data); |
| 360 | } | 434 | } |
| 361 | 435 | ||
| 362 | void WriteBlock(const VAddr addr, const u8* data, const size_t size) { | 436 | void WriteBlock(const VAddr dest_addr, const void* src_buffer, const size_t size) { |
| 363 | for (u32 offset = 0; offset < size; offset++) { | 437 | size_t remaining_size = size; |
| 364 | Write8(addr + offset, data[offset]); | 438 | size_t page_index = dest_addr >> PAGE_BITS; |
| 439 | size_t page_offset = dest_addr & PAGE_MASK; | ||
| 440 | |||
| 441 | while (remaining_size > 0) { | ||
| 442 | const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||
| 443 | const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||
| 444 | |||
| 445 | switch (current_page_table->attributes[page_index]) { | ||
| 446 | case PageType::Unmapped: { | ||
| 447 | LOG_ERROR(HW_Memory, "unmapped WriteBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | ||
| 448 | break; | ||
| 449 | } | ||
| 450 | case PageType::Memory: { | ||
| 451 | DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||
| 452 | |||
| 453 | u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; | ||
| 454 | std::memcpy(dest_ptr, src_buffer, copy_amount); | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | case PageType::Special: { | ||
| 458 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 459 | |||
| 460 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||
| 461 | break; | ||
| 462 | } | ||
| 463 | case PageType::RasterizerCachedMemory: { | ||
| 464 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 465 | |||
| 466 | std::memcpy(GetPointerFromVMA(current_vaddr), src_buffer, copy_amount); | ||
| 467 | break; | ||
| 468 | } | ||
| 469 | case PageType::RasterizerCachedSpecial: { | ||
| 470 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 471 | |||
| 472 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 473 | |||
| 474 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, src_buffer, copy_amount); | ||
| 475 | break; | ||
| 476 | } | ||
| 477 | default: | ||
| 478 | UNREACHABLE(); | ||
| 479 | } | ||
| 480 | |||
| 481 | page_index++; | ||
| 482 | page_offset = 0; | ||
| 483 | src_buffer = static_cast<const u8*>(src_buffer) + copy_amount; | ||
| 484 | remaining_size -= copy_amount; | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | void ZeroBlock(const VAddr dest_addr, const size_t size) { | ||
| 489 | size_t remaining_size = size; | ||
| 490 | size_t page_index = dest_addr >> PAGE_BITS; | ||
| 491 | size_t page_offset = dest_addr & PAGE_MASK; | ||
| 492 | |||
| 493 | static const std::array<u8, PAGE_SIZE> zeros = {}; | ||
| 494 | |||
| 495 | while (remaining_size > 0) { | ||
| 496 | const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||
| 497 | const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||
| 498 | |||
| 499 | switch (current_page_table->attributes[page_index]) { | ||
| 500 | case PageType::Unmapped: { | ||
| 501 | LOG_ERROR(HW_Memory, "unmapped ZeroBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, dest_addr, size); | ||
| 502 | break; | ||
| 503 | } | ||
| 504 | case PageType::Memory: { | ||
| 505 | DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||
| 506 | |||
| 507 | u8* dest_ptr = current_page_table->pointers[page_index] + page_offset; | ||
| 508 | std::memset(dest_ptr, 0, copy_amount); | ||
| 509 | break; | ||
| 510 | } | ||
| 511 | case PageType::Special: { | ||
| 512 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 513 | |||
| 514 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); | ||
| 515 | break; | ||
| 516 | } | ||
| 517 | case PageType::RasterizerCachedMemory: { | ||
| 518 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 519 | |||
| 520 | std::memset(GetPointerFromVMA(current_vaddr), 0, copy_amount); | ||
| 521 | break; | ||
| 522 | } | ||
| 523 | case PageType::RasterizerCachedSpecial: { | ||
| 524 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 525 | |||
| 526 | RasterizerFlushAndInvalidateRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 527 | |||
| 528 | GetMMIOHandler(current_vaddr)->WriteBlock(current_vaddr, zeros.data(), copy_amount); | ||
| 529 | break; | ||
| 530 | } | ||
| 531 | default: | ||
| 532 | UNREACHABLE(); | ||
| 533 | } | ||
| 534 | |||
| 535 | page_index++; | ||
| 536 | page_offset = 0; | ||
| 537 | remaining_size -= copy_amount; | ||
| 538 | } | ||
| 539 | } | ||
| 540 | |||
| 541 | void CopyBlock(VAddr dest_addr, VAddr src_addr, const size_t size) { | ||
| 542 | size_t remaining_size = size; | ||
| 543 | size_t page_index = src_addr >> PAGE_BITS; | ||
| 544 | size_t page_offset = src_addr & PAGE_MASK; | ||
| 545 | |||
| 546 | while (remaining_size > 0) { | ||
| 547 | const size_t copy_amount = std::min(PAGE_SIZE - page_offset, remaining_size); | ||
| 548 | const VAddr current_vaddr = (page_index << PAGE_BITS) + page_offset; | ||
| 549 | |||
| 550 | switch (current_page_table->attributes[page_index]) { | ||
| 551 | case PageType::Unmapped: { | ||
| 552 | LOG_ERROR(HW_Memory, "unmapped CopyBlock @ 0x%08X (start address = 0x%08X, size = %zu)", current_vaddr, src_addr, size); | ||
| 553 | ZeroBlock(dest_addr, copy_amount); | ||
| 554 | break; | ||
| 555 | } | ||
| 556 | case PageType::Memory: { | ||
| 557 | DEBUG_ASSERT(current_page_table->pointers[page_index]); | ||
| 558 | const u8* src_ptr = current_page_table->pointers[page_index] + page_offset; | ||
| 559 | WriteBlock(dest_addr, src_ptr, copy_amount); | ||
| 560 | break; | ||
| 561 | } | ||
| 562 | case PageType::Special: { | ||
| 563 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 564 | |||
| 565 | std::vector<u8> buffer(copy_amount); | ||
| 566 | GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); | ||
| 567 | WriteBlock(dest_addr, buffer.data(), buffer.size()); | ||
| 568 | break; | ||
| 569 | } | ||
| 570 | case PageType::RasterizerCachedMemory: { | ||
| 571 | RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 572 | |||
| 573 | WriteBlock(dest_addr, GetPointerFromVMA(current_vaddr), copy_amount); | ||
| 574 | break; | ||
| 575 | } | ||
| 576 | case PageType::RasterizerCachedSpecial: { | ||
| 577 | DEBUG_ASSERT(GetMMIOHandler(current_vaddr)); | ||
| 578 | |||
| 579 | RasterizerFlushRegion(VirtualToPhysicalAddress(current_vaddr), copy_amount); | ||
| 580 | |||
| 581 | std::vector<u8> buffer(copy_amount); | ||
| 582 | GetMMIOHandler(current_vaddr)->ReadBlock(current_vaddr, buffer.data(), buffer.size()); | ||
| 583 | WriteBlock(dest_addr, buffer.data(), buffer.size()); | ||
| 584 | break; | ||
| 585 | } | ||
| 586 | default: | ||
| 587 | UNREACHABLE(); | ||
| 588 | } | ||
| 589 | |||
| 590 | page_index++; | ||
| 591 | page_offset = 0; | ||
| 592 | dest_addr += copy_amount; | ||
| 593 | src_addr += copy_amount; | ||
| 594 | remaining_size -= copy_amount; | ||
| 365 | } | 595 | } |
| 366 | } | 596 | } |
| 367 | 597 | ||
diff --git a/src/core/memory.h b/src/core/memory.h index 126d60471..ae5588dee 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -110,6 +110,9 @@ enum : VAddr { | |||
| 110 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | 110 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, |
| 111 | }; | 111 | }; |
| 112 | 112 | ||
| 113 | bool IsValidVirtualAddress(const VAddr addr); | ||
| 114 | bool IsValidPhysicalAddress(const PAddr addr); | ||
| 115 | |||
| 113 | u8 Read8(VAddr addr); | 116 | u8 Read8(VAddr addr); |
| 114 | u16 Read16(VAddr addr); | 117 | u16 Read16(VAddr addr); |
| 115 | u32 Read32(VAddr addr); | 118 | u32 Read32(VAddr addr); |
| @@ -120,7 +123,10 @@ void Write16(VAddr addr, u16 data); | |||
| 120 | void Write32(VAddr addr, u32 data); | 123 | void Write32(VAddr addr, u32 data); |
| 121 | void Write64(VAddr addr, u64 data); | 124 | void Write64(VAddr addr, u64 data); |
| 122 | 125 | ||
| 123 | void WriteBlock(VAddr addr, const u8* data, size_t size); | 126 | void ReadBlock(const VAddr src_addr, void* dest_buffer, size_t size); |
| 127 | void WriteBlock(const VAddr dest_addr, const void* src_buffer, size_t size); | ||
| 128 | void ZeroBlock(const VAddr dest_addr, const size_t size); | ||
| 129 | void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size); | ||
| 124 | 130 | ||
| 125 | u8* GetPointer(VAddr virtual_address); | 131 | u8* GetPointer(VAddr virtual_address); |
| 126 | 132 | ||
diff --git a/src/core/mmio.h b/src/core/mmio.h index 06b555e98..d76f005d8 100644 --- a/src/core/mmio.h +++ b/src/core/mmio.h | |||
| @@ -18,15 +18,21 @@ class MMIORegion { | |||
| 18 | public: | 18 | public: |
| 19 | virtual ~MMIORegion() = default; | 19 | virtual ~MMIORegion() = default; |
| 20 | 20 | ||
| 21 | virtual bool IsValidAddress(VAddr addr) = 0; | ||
| 22 | |||
| 21 | virtual u8 Read8(VAddr addr) = 0; | 23 | virtual u8 Read8(VAddr addr) = 0; |
| 22 | virtual u16 Read16(VAddr addr) = 0; | 24 | virtual u16 Read16(VAddr addr) = 0; |
| 23 | virtual u32 Read32(VAddr addr) = 0; | 25 | virtual u32 Read32(VAddr addr) = 0; |
| 24 | virtual u64 Read64(VAddr addr) = 0; | 26 | virtual u64 Read64(VAddr addr) = 0; |
| 25 | 27 | ||
| 28 | virtual bool ReadBlock(VAddr src_addr, void* dest_buffer, size_t size) = 0; | ||
| 29 | |||
| 26 | virtual void Write8(VAddr addr, u8 data) = 0; | 30 | virtual void Write8(VAddr addr, u8 data) = 0; |
| 27 | virtual void Write16(VAddr addr, u16 data) = 0; | 31 | virtual void Write16(VAddr addr, u16 data) = 0; |
| 28 | virtual void Write32(VAddr addr, u32 data) = 0; | 32 | virtual void Write32(VAddr addr, u32 data) = 0; |
| 29 | virtual void Write64(VAddr addr, u64 data) = 0; | 33 | virtual void Write64(VAddr addr, u64 data) = 0; |
| 34 | |||
| 35 | virtual bool WriteBlock(VAddr dest_addr, const void* src_buffer, size_t size) = 0; | ||
| 30 | }; | 36 | }; |
| 31 | 37 | ||
| 32 | using MMIORegionPointer = std::shared_ptr<MMIORegion>; | 38 | using MMIORegionPointer = std::shared_ptr<MMIORegion>; |