diff options
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 20 | ||||
| -rw-r--r-- | src/core/hle/function_wrappers.h | 38 | ||||
| -rw-r--r-- | src/core/hle/service/nwm/nwm_uds.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 66 |
4 files changed, 62 insertions, 64 deletions
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index be2b2e25f..d6be16ef6 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp | |||
| @@ -644,7 +644,7 @@ static void ReadMemory() { | |||
| 644 | 644 | ||
| 645 | auto start_offset = command_buffer + 1; | 645 | auto start_offset = command_buffer + 1; |
| 646 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 646 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 647 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 647 | VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 648 | 648 | ||
| 649 | start_offset = addr_pos + 1; | 649 | start_offset = addr_pos + 1; |
| 650 | u32 len = | 650 | u32 len = |
| @@ -656,12 +656,14 @@ static void ReadMemory() { | |||
| 656 | SendReply("E01"); | 656 | SendReply("E01"); |
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | const u8* data = Memory::GetPointer(addr); | 659 | if (!Memory::IsValidVirtualAddress(addr)) { |
| 660 | if (!data) { | ||
| 661 | return SendReply("E00"); | 660 | return SendReply("E00"); |
| 662 | } | 661 | } |
| 663 | 662 | ||
| 664 | MemToGdbHex(reply, data, len); | 663 | std::vector<u8> data(len); |
| 664 | Memory::ReadBlock(addr, data.data(), len); | ||
| 665 | |||
| 666 | MemToGdbHex(reply, data.data(), len); | ||
| 665 | reply[len * 2] = '\0'; | 667 | reply[len * 2] = '\0'; |
| 666 | SendReply(reinterpret_cast<char*>(reply)); | 668 | SendReply(reinterpret_cast<char*>(reply)); |
| 667 | } | 669 | } |
| @@ -670,18 +672,20 @@ static void ReadMemory() { | |||
| 670 | static void WriteMemory() { | 672 | static void WriteMemory() { |
| 671 | auto start_offset = command_buffer + 1; | 673 | auto start_offset = command_buffer + 1; |
| 672 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); | 674 | auto addr_pos = std::find(start_offset, command_buffer + command_length, ','); |
| 673 | PAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); | 675 | VAddr addr = HexToInt(start_offset, static_cast<u32>(addr_pos - start_offset)); |
| 674 | 676 | ||
| 675 | start_offset = addr_pos + 1; | 677 | start_offset = addr_pos + 1; |
| 676 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); | 678 | auto len_pos = std::find(start_offset, command_buffer + command_length, ':'); |
| 677 | u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); | 679 | u32 len = HexToInt(start_offset, static_cast<u32>(len_pos - start_offset)); |
| 678 | 680 | ||
| 679 | u8* dst = Memory::GetPointer(addr); | 681 | if (!Memory::IsValidVirtualAddress(addr)) { |
| 680 | if (!dst) { | ||
| 681 | return SendReply("E00"); | 682 | return SendReply("E00"); |
| 682 | } | 683 | } |
| 683 | 684 | ||
| 684 | GdbHexToMem(dst, len_pos + 1, len); | 685 | std::vector<u8> data(len); |
| 686 | |||
| 687 | GdbHexToMem(data.data(), len_pos + 1, len); | ||
| 688 | Memory::WriteBlock(addr, data.data(), len); | ||
| 685 | SendReply("OK"); | 689 | SendReply("OK"); |
| 686 | } | 690 | } |
| 687 | 691 | ||
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 5e6002f4e..f93439f21 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -58,22 +58,21 @@ void Wrap() { | |||
| 58 | FuncReturn(retval); | 58 | FuncReturn(retval); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| 61 | template <ResultCode func(s32*, u32*, s32, bool, s64)> | 61 | template <ResultCode func(s32*, VAddr, s32, bool, s64)> |
| 62 | void Wrap() { | 62 | void Wrap() { |
| 63 | s32 param_1 = 0; | 63 | s32 param_1 = 0; |
| 64 | s32 retval = func(¶m_1, (Kernel::Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), | 64 | s32 retval = |
| 65 | (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))) | 65 | func(¶m_1, PARAM(1), (s32)PARAM(2), (PARAM(3) != 0), (((s64)PARAM(4) << 32) | PARAM(0))) |
| 66 | .raw; | 66 | .raw; |
| 67 | 67 | ||
| 68 | Core::CPU().SetReg(1, (u32)param_1); | 68 | Core::CPU().SetReg(1, (u32)param_1); |
| 69 | FuncReturn(retval); | 69 | FuncReturn(retval); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | template <ResultCode func(s32*, u32*, s32, u32)> | 72 | template <ResultCode func(s32*, VAddr, s32, u32)> |
| 73 | void Wrap() { | 73 | void Wrap() { |
| 74 | s32 param_1 = 0; | 74 | s32 param_1 = 0; |
| 75 | u32 retval = | 75 | u32 retval = func(¶m_1, PARAM(1), (s32)PARAM(2), PARAM(3)).raw; |
| 76 | func(¶m_1, (Kernel::Handle*)Memory::GetPointer(PARAM(1)), (s32)PARAM(2), PARAM(3)).raw; | ||
| 77 | 76 | ||
| 78 | Core::CPU().SetReg(1, (u32)param_1); | 77 | Core::CPU().SetReg(1, (u32)param_1); |
| 79 | FuncReturn(retval); | 78 | FuncReturn(retval); |
| @@ -152,21 +151,6 @@ void Wrap() { | |||
| 152 | FuncReturn(func(PARAM(0)).raw); | 151 | FuncReturn(func(PARAM(0)).raw); |
| 153 | } | 152 | } |
| 154 | 153 | ||
| 155 | template <ResultCode func(s64*, u32, u32*, u32)> | ||
| 156 | void Wrap() { | ||
| 157 | FuncReturn(func((s64*)Memory::GetPointer(PARAM(0)), PARAM(1), | ||
| 158 | (u32*)Memory::GetPointer(PARAM(2)), (s32)PARAM(3)) | ||
| 159 | .raw); | ||
| 160 | } | ||
| 161 | |||
| 162 | template <ResultCode func(u32*, const char*)> | ||
| 163 | void Wrap() { | ||
| 164 | u32 param_1 = 0; | ||
| 165 | u32 retval = func(¶m_1, (char*)Memory::GetPointer(PARAM(1))).raw; | ||
| 166 | Core::CPU().SetReg(1, param_1); | ||
| 167 | FuncReturn(retval); | ||
| 168 | } | ||
| 169 | |||
| 170 | template <ResultCode func(u32*, s32, s32)> | 154 | template <ResultCode func(u32*, s32, s32)> |
| 171 | void Wrap() { | 155 | void Wrap() { |
| 172 | u32 param_1 = 0; | 156 | u32 param_1 = 0; |
| @@ -222,13 +206,11 @@ void Wrap() { | |||
| 222 | FuncReturn(func(PARAM(0), PARAM(1)).raw); | 206 | FuncReturn(func(PARAM(0), PARAM(1)).raw); |
| 223 | } | 207 | } |
| 224 | 208 | ||
| 225 | template <ResultCode func(Kernel::Handle*, Kernel::Handle*, const char*, u32)> | 209 | template <ResultCode func(Kernel::Handle*, Kernel::Handle*, VAddr, u32)> |
| 226 | void Wrap() { | 210 | void Wrap() { |
| 227 | Kernel::Handle param_1 = 0; | 211 | Kernel::Handle param_1 = 0; |
| 228 | Kernel::Handle param_2 = 0; | 212 | Kernel::Handle param_2 = 0; |
| 229 | u32 retval = func(¶m_1, ¶m_2, | 213 | u32 retval = func(¶m_1, ¶m_2, PARAM(2), PARAM(3)).raw; |
| 230 | reinterpret_cast<const char*>(Memory::GetPointer(PARAM(2))), PARAM(3)) | ||
| 231 | .raw; | ||
| 232 | Core::CPU().SetReg(1, param_1); | 214 | Core::CPU().SetReg(1, param_1); |
| 233 | Core::CPU().SetReg(2, param_2); | 215 | Core::CPU().SetReg(2, param_2); |
| 234 | FuncReturn(retval); | 216 | FuncReturn(retval); |
| @@ -268,9 +250,9 @@ void Wrap() { | |||
| 268 | func(((s64)PARAM(1) << 32) | PARAM(0)); | 250 | func(((s64)PARAM(1) << 32) | PARAM(0)); |
| 269 | } | 251 | } |
| 270 | 252 | ||
| 271 | template <void func(const char*, int len)> | 253 | template <void func(VAddr, int len)> |
| 272 | void Wrap() { | 254 | void Wrap() { |
| 273 | func((char*)Memory::GetPointer(PARAM(0)), PARAM(1)); | 255 | func(PARAM(0), PARAM(1)); |
| 274 | } | 256 | } |
| 275 | 257 | ||
| 276 | template <void func(u8)> | 258 | template <void func(u8)> |
diff --git a/src/core/hle/service/nwm/nwm_uds.cpp b/src/core/hle/service/nwm/nwm_uds.cpp index 0aa63cc1e..87a6b0eca 100644 --- a/src/core/hle/service/nwm/nwm_uds.cpp +++ b/src/core/hle/service/nwm/nwm_uds.cpp | |||
| @@ -975,7 +975,7 @@ void OnClientConnected(u16 network_node_id) { | |||
| 975 | } | 975 | } |
| 976 | 976 | ||
| 977 | const Interface::FunctionInfo FunctionTable[] = { | 977 | const Interface::FunctionInfo FunctionTable[] = { |
| 978 | {0x00010442, nullptr, "Initialize (deprecated)"}, | 978 | {0x000102C2, nullptr, "Initialize (deprecated)"}, |
| 979 | {0x00020000, nullptr, "Scrap"}, | 979 | {0x00020000, nullptr, "Scrap"}, |
| 980 | {0x00030000, Shutdown, "Shutdown"}, | 980 | {0x00030000, Shutdown, "Shutdown"}, |
| 981 | {0x00040402, nullptr, "CreateNetwork (deprecated)"}, | 981 | {0x00040402, nullptr, "CreateNetwork (deprecated)"}, |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 6be5db13f..e8ca419d5 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -201,17 +201,21 @@ static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) { | |||
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | /// Connect to an OS service given the port name, returns the handle to the port to out | 203 | /// Connect to an OS service given the port name, returns the handle to the port to out |
| 204 | static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) { | 204 | static ResultCode ConnectToPort(Kernel::Handle* out_handle, VAddr port_name_address) { |
| 205 | if (port_name == nullptr) | 205 | if (!Memory::IsValidVirtualAddress(port_name_address)) |
| 206 | return Kernel::ERR_NOT_FOUND; | 206 | return Kernel::ERR_NOT_FOUND; |
| 207 | if (std::strlen(port_name) > 11) | 207 | |
| 208 | static constexpr std::size_t PortNameMaxLength = 11; | ||
| 209 | // Read 1 char beyond the max allowed port name to detect names that are too long. | ||
| 210 | std::string port_name = Memory::ReadCString(port_name_address, PortNameMaxLength + 1); | ||
| 211 | if (port_name.size() > PortNameMaxLength) | ||
| 208 | return Kernel::ERR_PORT_NAME_TOO_LONG; | 212 | return Kernel::ERR_PORT_NAME_TOO_LONG; |
| 209 | 213 | ||
| 210 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); | 214 | LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name.c_str()); |
| 211 | 215 | ||
| 212 | auto it = Service::g_kernel_named_ports.find(port_name); | 216 | auto it = Service::g_kernel_named_ports.find(port_name); |
| 213 | if (it == Service::g_kernel_named_ports.end()) { | 217 | if (it == Service::g_kernel_named_ports.end()) { |
| 214 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); | 218 | LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name.c_str()); |
| 215 | return Kernel::ERR_NOT_FOUND; | 219 | return Kernel::ERR_NOT_FOUND; |
| 216 | } | 220 | } |
| 217 | 221 | ||
| @@ -303,12 +307,11 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds) | |||
| 303 | } | 307 | } |
| 304 | 308 | ||
| 305 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds | 309 | /// Wait for the given handles to synchronize, timeout after the specified nanoseconds |
| 306 | static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 handle_count, | 310 | static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 handle_count, |
| 307 | bool wait_all, s64 nano_seconds) { | 311 | bool wait_all, s64 nano_seconds) { |
| 308 | Kernel::Thread* thread = Kernel::GetCurrentThread(); | 312 | Kernel::Thread* thread = Kernel::GetCurrentThread(); |
| 309 | 313 | ||
| 310 | // Check if 'handles' is invalid | 314 | if (!Memory::IsValidVirtualAddress(handles_address)) |
| 311 | if (handles == nullptr) | ||
| 312 | return Kernel::ERR_INVALID_POINTER; | 315 | return Kernel::ERR_INVALID_POINTER; |
| 313 | 316 | ||
| 314 | // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If | 317 | // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If |
| @@ -323,7 +326,8 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha | |||
| 323 | std::vector<ObjectPtr> objects(handle_count); | 326 | std::vector<ObjectPtr> objects(handle_count); |
| 324 | 327 | ||
| 325 | for (int i = 0; i < handle_count; ++i) { | 328 | for (int i = 0; i < handle_count; ++i) { |
| 326 | auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]); | 329 | Kernel::Handle handle = Memory::Read32(handles_address + i * sizeof(Kernel::Handle)); |
| 330 | auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle); | ||
| 327 | if (object == nullptr) | 331 | if (object == nullptr) |
| 328 | return ERR_INVALID_HANDLE; | 332 | return ERR_INVALID_HANDLE; |
| 329 | objects[i] = object; | 333 | objects[i] = object; |
| @@ -452,10 +456,9 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha | |||
| 452 | } | 456 | } |
| 453 | 457 | ||
| 454 | /// In a single operation, sends a IPC reply and waits for a new request. | 458 | /// In a single operation, sends a IPC reply and waits for a new request. |
| 455 | static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handle_count, | 459 | static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_count, |
| 456 | Kernel::Handle reply_target) { | 460 | Kernel::Handle reply_target) { |
| 457 | // 'handles' has to be a valid pointer even if 'handle_count' is 0. | 461 | if (!Memory::IsValidVirtualAddress(handles_address)) |
| 458 | if (handles == nullptr) | ||
| 459 | return Kernel::ERR_INVALID_POINTER; | 462 | return Kernel::ERR_INVALID_POINTER; |
| 460 | 463 | ||
| 461 | // Check if 'handle_count' is invalid | 464 | // Check if 'handle_count' is invalid |
| @@ -466,7 +469,8 @@ static ResultCode ReplyAndReceive(s32* index, Kernel::Handle* handles, s32 handl | |||
| 466 | std::vector<ObjectPtr> objects(handle_count); | 469 | std::vector<ObjectPtr> objects(handle_count); |
| 467 | 470 | ||
| 468 | for (int i = 0; i < handle_count; ++i) { | 471 | for (int i = 0; i < handle_count; ++i) { |
| 469 | auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handles[i]); | 472 | Kernel::Handle handle = Memory::Read32(handles_address + i * sizeof(Kernel::Handle)); |
| 473 | auto object = Kernel::g_handle_table.Get<Kernel::WaitObject>(handle); | ||
| 470 | if (object == nullptr) | 474 | if (object == nullptr) |
| 471 | return ERR_INVALID_HANDLE; | 475 | return ERR_INVALID_HANDLE; |
| 472 | objects[i] = object; | 476 | objects[i] = object; |
| @@ -619,8 +623,10 @@ static void Break(u8 break_reason) { | |||
| 619 | } | 623 | } |
| 620 | 624 | ||
| 621 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit | 625 | /// Used to output a message on a debug hardware unit - does nothing on a retail unit |
| 622 | static void OutputDebugString(const char* string, int len) { | 626 | static void OutputDebugString(VAddr address, int len) { |
| 623 | LOG_DEBUG(Debug_Emulated, "%.*s", len, string); | 627 | std::vector<char> string(len); |
| 628 | Memory::ReadBlock(address, string.data(), len); | ||
| 629 | LOG_DEBUG(Debug_Emulated, "%.*s", len, string.data()); | ||
| 624 | } | 630 | } |
| 625 | 631 | ||
| 626 | /// Get resource limit | 632 | /// Get resource limit |
| @@ -638,9 +644,9 @@ static ResultCode GetResourceLimit(Kernel::Handle* resource_limit, Kernel::Handl | |||
| 638 | } | 644 | } |
| 639 | 645 | ||
| 640 | /// Get resource limit current values | 646 | /// Get resource limit current values |
| 641 | static ResultCode GetResourceLimitCurrentValues(s64* values, Kernel::Handle resource_limit_handle, | 647 | static ResultCode GetResourceLimitCurrentValues(VAddr values, Kernel::Handle resource_limit_handle, |
| 642 | u32* names, u32 name_count) { | 648 | VAddr names, u32 name_count) { |
| 643 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 649 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%08X, name_count=%d", |
| 644 | resource_limit_handle, names, name_count); | 650 | resource_limit_handle, names, name_count); |
| 645 | 651 | ||
| 646 | SharedPtr<Kernel::ResourceLimit> resource_limit = | 652 | SharedPtr<Kernel::ResourceLimit> resource_limit = |
| @@ -648,16 +654,19 @@ static ResultCode GetResourceLimitCurrentValues(s64* values, Kernel::Handle reso | |||
| 648 | if (resource_limit == nullptr) | 654 | if (resource_limit == nullptr) |
| 649 | return ERR_INVALID_HANDLE; | 655 | return ERR_INVALID_HANDLE; |
| 650 | 656 | ||
| 651 | for (unsigned int i = 0; i < name_count; ++i) | 657 | for (unsigned int i = 0; i < name_count; ++i) { |
| 652 | values[i] = resource_limit->GetCurrentResourceValue(names[i]); | 658 | u32 name = Memory::Read32(names + i * sizeof(u32)); |
| 659 | s64 value = resource_limit->GetCurrentResourceValue(name); | ||
| 660 | Memory::Write64(values + i * sizeof(u64), value); | ||
| 661 | } | ||
| 653 | 662 | ||
| 654 | return RESULT_SUCCESS; | 663 | return RESULT_SUCCESS; |
| 655 | } | 664 | } |
| 656 | 665 | ||
| 657 | /// Get resource limit max values | 666 | /// Get resource limit max values |
| 658 | static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resource_limit_handle, | 667 | static ResultCode GetResourceLimitLimitValues(VAddr values, Kernel::Handle resource_limit_handle, |
| 659 | u32* names, u32 name_count) { | 668 | VAddr names, u32 name_count) { |
| 660 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%p, name_count=%d", | 669 | LOG_TRACE(Kernel_SVC, "called resource_limit=%08X, names=%08X, name_count=%d", |
| 661 | resource_limit_handle, names, name_count); | 670 | resource_limit_handle, names, name_count); |
| 662 | 671 | ||
| 663 | SharedPtr<Kernel::ResourceLimit> resource_limit = | 672 | SharedPtr<Kernel::ResourceLimit> resource_limit = |
| @@ -665,8 +674,11 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resour | |||
| 665 | if (resource_limit == nullptr) | 674 | if (resource_limit == nullptr) |
| 666 | return ERR_INVALID_HANDLE; | 675 | return ERR_INVALID_HANDLE; |
| 667 | 676 | ||
| 668 | for (unsigned int i = 0; i < name_count; ++i) | 677 | for (unsigned int i = 0; i < name_count; ++i) { |
| 669 | values[i] = resource_limit->GetMaxResourceValue(names[i]); | 678 | u32 name = Memory::Read32(names + i * sizeof(u32)); |
| 679 | s64 value = resource_limit->GetMaxResourceValue(names); | ||
| 680 | Memory::Write64(values + i * sizeof(u64), value); | ||
| 681 | } | ||
| 670 | 682 | ||
| 671 | return RESULT_SUCCESS; | 683 | return RESULT_SUCCESS; |
| 672 | } | 684 | } |
| @@ -1098,9 +1110,9 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si | |||
| 1098 | } | 1110 | } |
| 1099 | 1111 | ||
| 1100 | static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client_port, | 1112 | static ResultCode CreatePort(Kernel::Handle* server_port, Kernel::Handle* client_port, |
| 1101 | const char* name, u32 max_sessions) { | 1113 | VAddr name_address, u32 max_sessions) { |
| 1102 | // TODO(Subv): Implement named ports. | 1114 | // TODO(Subv): Implement named ports. |
| 1103 | ASSERT_MSG(name == nullptr, "Named ports are currently unimplemented"); | 1115 | ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented"); |
| 1104 | 1116 | ||
| 1105 | using Kernel::ServerPort; | 1117 | using Kernel::ServerPort; |
| 1106 | using Kernel::ClientPort; | 1118 | using Kernel::ClientPort; |