diff options
| author | 2018-01-18 16:54:34 -0300 | |
|---|---|---|
| committer | 2018-01-18 14:54:34 -0500 | |
| commit | 59575d5cae573b57eb9e1e611e2c25ceb935ec0a (patch) | |
| tree | ec98ab8ec825b0001face3a4e7c9b821bd67e0b2 | |
| parent | Start to implement/stub BSD:U and SFDNSRES services (#78) (diff) | |
| download | yuzu-59575d5cae573b57eb9e1e611e2c25ceb935ec0a.tar.gz yuzu-59575d5cae573b57eb9e1e611e2c25ceb935ec0a.tar.xz yuzu-59575d5cae573b57eb9e1e611e2c25ceb935ec0a.zip | |
Stub PopLaunchParameter and implement Buffer C Descriptors reading on hle_ipc (#96)
* Stub PopLaunchParameter and implement Buffer C Descriptors reading
* Address PR feedback
* Ensure we push a u64 not a size_t
* Fix formatting
| -rw-r--r-- | src/core/hle/ipc.h | 4 | ||||
| -rw-r--r-- | src/core/hle/ipc_helpers.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.cpp | 34 | ||||
| -rw-r--r-- | src/core/hle/kernel/hle_ipc.h | 6 | ||||
| -rw-r--r-- | src/core/hle/service/am/applet_oe.cpp | 86 |
5 files changed, 127 insertions, 7 deletions
diff --git a/src/core/hle/ipc.h b/src/core/hle/ipc.h index 1840fac12..0dcaede67 100644 --- a/src/core/hle/ipc.h +++ b/src/core/hle/ipc.h | |||
| @@ -133,6 +133,10 @@ struct BufferDescriptorC { | |||
| 133 | address |= static_cast<VAddr>(address_bits_32_47) << 32; | 133 | address |= static_cast<VAddr>(address_bits_32_47) << 32; |
| 134 | return address; | 134 | return address; |
| 135 | } | 135 | } |
| 136 | |||
| 137 | u64 Size() const { | ||
| 138 | return static_cast<u64>(size); | ||
| 139 | } | ||
| 136 | }; | 140 | }; |
| 137 | static_assert(sizeof(BufferDescriptorC) == 8, "BufferDescriptorC size is incorrect"); | 141 | static_assert(sizeof(BufferDescriptorC) == 8, "BufferDescriptorC size is incorrect"); |
| 138 | 142 | ||
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 25530a3c8..4c9b0de28 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h | |||
| @@ -54,6 +54,10 @@ public: | |||
| 54 | unsigned GetCurrentOffset() const { | 54 | unsigned GetCurrentOffset() const { |
| 55 | return static_cast<unsigned>(index); | 55 | return static_cast<unsigned>(index); |
| 56 | } | 56 | } |
| 57 | |||
| 58 | void SetCurrentOffset(unsigned offset) { | ||
| 59 | index = static_cast<ptrdiff_t>(offset); | ||
| 60 | } | ||
| 57 | }; | 61 | }; |
| 58 | 62 | ||
| 59 | class RequestBuilder : public RequestHelperBase { | 63 | class RequestBuilder : public RequestHelperBase { |
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp index ac62a0d5a..73bb6a8be 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp | |||
| @@ -81,13 +81,8 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 81 | for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { | 81 | for (unsigned i = 0; i < command_header->num_buf_w_descriptors; ++i) { |
| 82 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 82 | buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); |
| 83 | } | 83 | } |
| 84 | if (command_header->buf_c_descriptor_flags != | 84 | |
| 85 | IPC::CommandHeader::BufferDescriptorCFlag::Disabled) { | 85 | buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; |
| 86 | if (command_header->buf_c_descriptor_flags != | ||
| 87 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | ||
| 88 | UNIMPLEMENTED(); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | 86 | ||
| 92 | // Padding to align to 16 bytes | 87 | // Padding to align to 16 bytes |
| 93 | rp.AlignWithPadding(); | 88 | rp.AlignWithPadding(); |
| @@ -117,6 +112,31 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) { | |||
| 117 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 112 | ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); |
| 118 | } | 113 | } |
| 119 | 114 | ||
| 115 | rp.SetCurrentOffset(buffer_c_offset); | ||
| 116 | |||
| 117 | // For Inline buffers, the response data is written directly to buffer_c_offset | ||
| 118 | // and in this case we don't have any BufferDescriptorC on the request. | ||
| 119 | if (command_header->buf_c_descriptor_flags > | ||
| 120 | IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { | ||
| 121 | if (command_header->buf_c_descriptor_flags == | ||
| 122 | IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | ||
| 123 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | ||
| 124 | } else { | ||
| 125 | unsigned num_buf_c_descriptors = | ||
| 126 | static_cast<unsigned>(command_header->buf_c_descriptor_flags.Value()) - 2; | ||
| 127 | |||
| 128 | // This is used to detect possible underflows, in case something is broken | ||
| 129 | // with the two ifs above and the flags value is == 0 || == 1. | ||
| 130 | ASSERT(num_buf_c_descriptors < 14); | ||
| 131 | |||
| 132 | for (unsigned i = 0; i < num_buf_c_descriptors; ++i) { | ||
| 133 | buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | ||
| 134 | } | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | rp.SetCurrentOffset(data_payload_offset); | ||
| 139 | |||
| 120 | command = rp.Pop<u32_le>(); | 140 | command = rp.Pop<u32_le>(); |
| 121 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. | 141 | rp.Skip(1, false); // The command is actually an u64, but we don't use the high part. |
| 122 | } | 142 | } |
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h index 6dceb766d..80fa48d7f 100644 --- a/src/core/hle/kernel/hle_ipc.h +++ b/src/core/hle/kernel/hle_ipc.h | |||
| @@ -143,6 +143,10 @@ public: | |||
| 143 | return buffer_b_desciptors; | 143 | return buffer_b_desciptors; |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | const std::vector<IPC::BufferDescriptorC>& BufferDescriptorC() const { | ||
| 147 | return buffer_c_desciptors; | ||
| 148 | } | ||
| 149 | |||
| 146 | const std::unique_ptr<IPC::DomainMessageHeader>& GetDomainMessageHeader() const { | 150 | const std::unique_ptr<IPC::DomainMessageHeader>& GetDomainMessageHeader() const { |
| 147 | return domain_message_header; | 151 | return domain_message_header; |
| 148 | } | 152 | } |
| @@ -200,8 +204,10 @@ private: | |||
| 200 | std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; | 204 | std::vector<IPC::BufferDescriptorABW> buffer_a_desciptors; |
| 201 | std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; | 205 | std::vector<IPC::BufferDescriptorABW> buffer_b_desciptors; |
| 202 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; | 206 | std::vector<IPC::BufferDescriptorABW> buffer_w_desciptors; |
| 207 | std::vector<IPC::BufferDescriptorC> buffer_c_desciptors; | ||
| 203 | 208 | ||
| 204 | unsigned data_payload_offset{}; | 209 | unsigned data_payload_offset{}; |
| 210 | unsigned buffer_c_offset{}; | ||
| 205 | u32_le command{}; | 211 | u32_le command{}; |
| 206 | }; | 212 | }; |
| 207 | 213 | ||
diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index b360e7e5f..0d7f9c03d 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp | |||
| @@ -201,10 +201,76 @@ private: | |||
| 201 | Kernel::SharedPtr<Kernel::Event> event; | 201 | Kernel::SharedPtr<Kernel::Event> event; |
| 202 | }; | 202 | }; |
| 203 | 203 | ||
| 204 | class IStorageAccessor final : public ServiceFramework<IStorageAccessor> { | ||
| 205 | public: | ||
| 206 | explicit IStorageAccessor(std::vector<u8> buffer) | ||
| 207 | : ServiceFramework("IStorageAccessor"), buffer(std::move(buffer)) { | ||
| 208 | static const FunctionInfo functions[] = { | ||
| 209 | {0, &IStorageAccessor::GetSize, "GetSize"}, | ||
| 210 | {11, &IStorageAccessor::Read, "Read"}, | ||
| 211 | }; | ||
| 212 | RegisterHandlers(functions); | ||
| 213 | } | ||
| 214 | |||
| 215 | private: | ||
| 216 | std::vector<u8> buffer; | ||
| 217 | |||
| 218 | void GetSize(Kernel::HLERequestContext& ctx) { | ||
| 219 | IPC::RequestBuilder rb{ctx, 4}; | ||
| 220 | |||
| 221 | rb.Push(RESULT_SUCCESS); | ||
| 222 | rb.Push(static_cast<u64>(buffer.size())); | ||
| 223 | |||
| 224 | LOG_DEBUG(Service, "called"); | ||
| 225 | } | ||
| 226 | |||
| 227 | void Read(Kernel::HLERequestContext& ctx) { | ||
| 228 | IPC::RequestParser rp{ctx}; | ||
| 229 | |||
| 230 | u64 offset = rp.Pop<u64>(); | ||
| 231 | |||
| 232 | const auto& output_buffer = ctx.BufferDescriptorC()[0]; | ||
| 233 | |||
| 234 | ASSERT(offset + output_buffer.Size() <= buffer.size()); | ||
| 235 | |||
| 236 | Memory::WriteBlock(output_buffer.Address(), buffer.data() + offset, output_buffer.Size()); | ||
| 237 | |||
| 238 | IPC::RequestBuilder rb{ctx, 2}; | ||
| 239 | |||
| 240 | rb.Push(RESULT_SUCCESS); | ||
| 241 | |||
| 242 | LOG_DEBUG(Service, "called"); | ||
| 243 | } | ||
| 244 | }; | ||
| 245 | |||
| 246 | class IStorage final : public ServiceFramework<IStorage> { | ||
| 247 | public: | ||
| 248 | explicit IStorage(std::vector<u8> buffer) | ||
| 249 | : ServiceFramework("IStorage"), buffer(std::move(buffer)) { | ||
| 250 | static const FunctionInfo functions[] = { | ||
| 251 | {0, &IStorage::Open, "Open"}, | ||
| 252 | }; | ||
| 253 | RegisterHandlers(functions); | ||
| 254 | } | ||
| 255 | |||
| 256 | private: | ||
| 257 | std::vector<u8> buffer; | ||
| 258 | |||
| 259 | void Open(Kernel::HLERequestContext& ctx) { | ||
| 260 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 261 | |||
| 262 | rb.Push(RESULT_SUCCESS); | ||
| 263 | rb.PushIpcInterface<AM::IStorageAccessor>(buffer); | ||
| 264 | |||
| 265 | LOG_DEBUG(Service, "called"); | ||
| 266 | } | ||
| 267 | }; | ||
| 268 | |||
| 204 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { | 269 | class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> { |
| 205 | public: | 270 | public: |
| 206 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { | 271 | IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { |
| 207 | static const FunctionInfo functions[] = { | 272 | static const FunctionInfo functions[] = { |
| 273 | {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, | ||
| 208 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, | 274 | {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, |
| 209 | {66, &IApplicationFunctions::InitializeGamePlayRecording, | 275 | {66, &IApplicationFunctions::InitializeGamePlayRecording, |
| 210 | "InitializeGamePlayRecording"}, | 276 | "InitializeGamePlayRecording"}, |
| @@ -215,6 +281,26 @@ public: | |||
| 215 | } | 281 | } |
| 216 | 282 | ||
| 217 | private: | 283 | private: |
| 284 | void PopLaunchParameter(Kernel::HLERequestContext& ctx) { | ||
| 285 | constexpr u8 data[0x88] = { | ||
| 286 | 0xca, 0x97, 0x94, 0xc7, // Magic | ||
| 287 | 1, 0, 0, 0, // IsAccountSelected (bool) | ||
| 288 | 1, 0, 0, 0, // User Id (word 0) | ||
| 289 | 0, 0, 0, 0, // User Id (word 1) | ||
| 290 | 0, 0, 0, 0, // User Id (word 2) | ||
| 291 | 0, 0, 0, 0 // User Id (word 3) | ||
| 292 | }; | ||
| 293 | |||
| 294 | std::vector<u8> buffer(data, data + sizeof(data)); | ||
| 295 | |||
| 296 | IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||
| 297 | |||
| 298 | rb.Push(RESULT_SUCCESS); | ||
| 299 | rb.PushIpcInterface<AM::IStorage>(buffer); | ||
| 300 | |||
| 301 | LOG_DEBUG(Service, "called"); | ||
| 302 | } | ||
| 303 | |||
| 218 | void SetTerminateResult(Kernel::HLERequestContext& ctx) { | 304 | void SetTerminateResult(Kernel::HLERequestContext& ctx) { |
| 219 | // Takes an input u32 Result, no output. | 305 | // Takes an input u32 Result, no output. |
| 220 | // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. | 306 | // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. |