summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/ipc_helpers.h160
1 files changed, 88 insertions, 72 deletions
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 6089c39c7..68508caba 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -50,9 +50,9 @@ public:
50 template <typename T> 50 template <typename T>
51 void Push(T value); 51 void Push(T value);
52 52
53 template <> 53 void Push(u32 value) {
54 void Push(u32); 54 cmdbuf[index++] = value;
55 55 }
56 template <typename First, class... Other> 56 template <typename First, class... Other>
57 void Push(First first_value, const Other&... other_values) { 57 void Push(First first_value, const Other&... other_values) {
58 Push(first_value); 58 Push(first_value);
@@ -86,7 +86,7 @@ public:
86 86
87 void PushCurrentPIDHandle() { 87 void PushCurrentPIDHandle() {
88 Push(CallingPidDesc()); 88 Push(CallingPidDesc());
89 Push<u32>(0); 89 Push(u32(0));
90 } 90 }
91 91
92 void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) { 92 void PushStaticBuffer(VAddr buffer_vaddr, u32 size, u8 buffer_id) {
@@ -100,6 +100,24 @@ public:
100 } 100 }
101}; 101};
102 102
103/// Push ///
104
105template <>
106inline void RequestBuilder::Push<u32>(u32 value) {
107 Push(value);
108}
109
110template <>
111inline void RequestBuilder::Push<u64>(u64 value) {
112 Push(static_cast<u32>(value));
113 Push(static_cast<u32>(value >> 32));
114}
115
116template <>
117inline void RequestBuilder::Push<ResultCode>(ResultCode value) {
118 Push(value.raw);
119}
120
103class RequestParser : public RequestHelperBase { 121class RequestParser : public RequestHelperBase {
104public: 122public:
105 RequestParser(u32* command_buffer, Header command_header) 123 RequestParser(u32* command_buffer, Header command_header)
@@ -123,39 +141,16 @@ public:
123 template <typename T> 141 template <typename T>
124 T Pop(); 142 T Pop();
125 143
126 template <>
127 u32 Pop<u32>();
128
129 template <typename T> 144 template <typename T>
130 void Pop(T& value) { 145 void Pop(T& value);
131 value = Pop<T>();
132 }
133 146
134 template <typename First, class... Other> 147 template <typename First, class... Other>
135 void Pop(First& first_value, Other&... other_values) { 148 void Pop(First& first_value, Other&... other_values);
136 first_value = Pop<First>();
137 Pop(other_values...);
138 }
139 149
140 Kernel::Handle PopHandle() { 150 Kernel::Handle PopHandle();
141 const u32 handle_descriptor = Pop<u32>();
142 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
143 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
144 DEBUG_ASSERT_MSG(HandleNumberFromDesc(handle_descriptor) == 1,
145 "Descriptor indicates that there isn't exactly one handle");
146 return Pop<Kernel::Handle>();
147 }
148 151
149 template <typename... H> 152 template <typename... H>
150 void PopHandles(H&... handles) { 153 void PopHandles(H&... handles);
151 const u32 handle_descriptor = Pop<u32>();
152 const int handles_number = sizeof...(H);
153 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
154 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
155 DEBUG_ASSERT_MSG(handles_number == HandleNumberFromDesc(handle_descriptor),
156 "Number of handles doesn't match the descriptor");
157 Pop(static_cast<Kernel::Handle&>(handles)...);
158 }
159 154
160 /** 155 /**
161 * @brief Pops the static buffer vaddr 156 * @brief Pops the static buffer vaddr
@@ -171,22 +166,7 @@ public:
171 * buffer information 166 * buffer information
172 * Please note that the setup uses virtual addresses. 167 * Please note that the setup uses virtual addresses.
173 */ 168 */
174 VAddr PopStaticBuffer(size_t* data_size = nullptr, bool useStaticBuffersToGetVaddr = false) { 169 VAddr PopStaticBuffer(size_t* data_size = nullptr, bool useStaticBuffersToGetVaddr = false);
175 const u32 sbuffer_descriptor = Pop<u32>();
176 StaticBufferDescInfo bufferInfo{sbuffer_descriptor};
177 if (data_size != nullptr)
178 *data_size = bufferInfo.size;
179 if (!useStaticBuffersToGetVaddr)
180 return Pop<VAddr>();
181 else {
182 ASSERT_MSG(0, "remove the assert if multiprocess/IPC translation are implemented.");
183 // The buffer has already been copied to the static buffer by the kernel during
184 // translation
185 Pop<VAddr>(); // Pop the calling process buffer address
186 // and get the vaddr from the static buffers
187 return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1];
188 }
189 }
190 170
191 /** 171 /**
192 * @brief Pops the mapped buffer vaddr 172 * @brief Pops the mapped buffer vaddr
@@ -197,26 +177,14 @@ public:
197 * buffer 177 * buffer
198 */ 178 */
199 VAddr PopMappedBuffer(size_t* data_size = nullptr, 179 VAddr PopMappedBuffer(size_t* data_size = nullptr,
200 MappedBufferPermissions* buffer_perms = nullptr) { 180 MappedBufferPermissions* buffer_perms = nullptr);
201 const u32 sbuffer_descriptor = Pop<u32>();
202 MappedBufferDescInfo bufferInfo{sbuffer_descriptor};
203 if (data_size != nullptr)
204 *data_size = bufferInfo.size;
205 if (buffer_perms != nullptr)
206 *buffer_perms = bufferInfo.perms;
207 return Pop<VAddr>();
208 }
209 181
210 /** 182 /**
211 * @brief Reads the next normal parameters as a struct, by copying it 183 * @brief Reads the next normal parameters as a struct, by copying it
212 * @note: The output class must be correctly packed/padded to fit hardware layout. 184 * @note: The output class must be correctly packed/padded to fit hardware layout.
213 */ 185 */
214 template <typename T> 186 template <typename T>
215 void PopRaw(T& value) { 187 void PopRaw(T& value);
216 static_assert(std::is_trivially_copyable<T>(), "Raw types should be trivially copyable");
217 std::memcpy(&value, cmdbuf + index, sizeof(T));
218 index += (sizeof(T) + 3) / 4; // round up to word length
219 }
220}; 188};
221 189
222/// Pop /// 190/// Pop ///
@@ -238,22 +206,70 @@ inline ResultCode RequestParser::Pop<ResultCode>() {
238 return ResultCode{Pop<u32>()}; 206 return ResultCode{Pop<u32>()};
239} 207}
240 208
241/// Push /// 209template <typename T>
210void RequestParser::Pop(T& value) {
211 value = Pop<T>();
212}
242 213
243template <> 214template <typename First, class... Other>
244inline void RequestBuilder::Push<u32>(u32 value) { 215void RequestParser::Pop(First& first_value, Other&... other_values) {
245 cmdbuf[index++] = value; 216 first_value = Pop<First>();
217 Pop(other_values...);
246} 218}
247 219
248template <> 220inline Kernel::Handle RequestParser::PopHandle() {
249inline void RequestBuilder::Push<u64>(u64 value) { 221 const u32 handle_descriptor = Pop<u32>();
250 Push(static_cast<u32>(value)); 222 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
251 Push(static_cast<u32>(value >> 32)); 223 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
224 DEBUG_ASSERT_MSG(HandleNumberFromDesc(handle_descriptor) == 1,
225 "Descriptor indicates that there isn't exactly one handle");
226 return Pop<Kernel::Handle>();
252} 227}
253 228
254template <> 229template <typename... H>
255inline void RequestBuilder::Push<ResultCode>(ResultCode value) { 230void RequestParser::PopHandles(H&... handles) {
256 Push(value.raw); 231 const u32 handle_descriptor = Pop<u32>();
232 const int handles_number = sizeof...(H);
233 DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor),
234 "Tried to pop handle(s) but the descriptor is not a handle descriptor");
235 DEBUG_ASSERT_MSG(handles_number == HandleNumberFromDesc(handle_descriptor),
236 "Number of handles doesn't match the descriptor");
237 Pop(static_cast<Kernel::Handle&>(handles)...);
238}
239
240inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) {
241 const u32 sbuffer_descriptor = Pop<u32>();
242 StaticBufferDescInfo bufferInfo{sbuffer_descriptor};
243 if (data_size != nullptr)
244 *data_size = bufferInfo.size;
245 if (!useStaticBuffersToGetVaddr)
246 return Pop<VAddr>();
247 else {
248 ASSERT_MSG(0, "remove the assert if multiprocess/IPC translation are implemented.");
249 // The buffer has already been copied to the static buffer by the kernel during
250 // translation
251 Pop<VAddr>(); // Pop the calling process buffer address
252 // and get the vaddr from the static buffers
253 return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1];
254 }
255}
256
257inline VAddr RequestParser::PopMappedBuffer(size_t* data_size,
258 MappedBufferPermissions* buffer_perms) {
259 const u32 sbuffer_descriptor = Pop<u32>();
260 MappedBufferDescInfo bufferInfo{sbuffer_descriptor};
261 if (data_size != nullptr)
262 *data_size = bufferInfo.size;
263 if (buffer_perms != nullptr)
264 *buffer_perms = bufferInfo.perms;
265 return Pop<VAddr>();
266}
267
268template <typename T>
269void RequestParser::PopRaw(T& value) {
270 static_assert(std::is_trivially_copyable<T>(), "Raw types should be trivially copyable");
271 std::memcpy(&value, cmdbuf + index, sizeof(T));
272 index += (sizeof(T) + 3) / 4; // round up to word length
257} 273}
258 274
259} // namespace IPC 275} // namespace IPC