| 
									
										
										
										
											2022-04-23 04:59:50 -04:00
										 |  |  | // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | 
					
						
							|  |  |  | // SPDX-License-Identifier: GPL-2.0-or-later
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-31 08:06:09 -04:00
										 |  |  | #include <algorithm>
 | 
					
						
							| 
									
										
										
										
											2018-08-01 22:40:00 -04:00
										 |  |  | #include <array>
 | 
					
						
							|  |  |  | #include <sstream>
 | 
					
						
							| 
									
										
										
										
											2018-07-18 19:02:47 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | #include <boost/range/algorithm_ext/erase.hpp>
 | 
					
						
							| 
									
										
										
										
											2018-08-01 22:40:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | #include "common/assert.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  | #include "common/common_funcs.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | #include "common/common_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-01 22:40:00 -04:00
										 |  |  | #include "common/logging/log.h"
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | #include "core/hle/ipc_helpers.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | #include "core/hle/kernel/hle_ipc.h"
 | 
					
						
							| 
									
										
										
										
											2021-10-07 13:30:20 -04:00
										 |  |  | #include "core/hle/kernel/k_auto_object.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-24 02:40:31 -07:00
										 |  |  | #include "core/hle/kernel/k_handle_table.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-23 22:04:28 -07:00
										 |  |  | #include "core/hle/kernel/k_process.h"
 | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  | #include "core/hle/kernel/k_server_port.h"
 | 
					
						
							| 
									
										
										
										
											2021-04-13 17:48:37 -07:00
										 |  |  | #include "core/hle/kernel/k_server_session.h"
 | 
					
						
							| 
									
										
										
										
											2020-12-30 23:01:08 -08:00
										 |  |  | #include "core/hle/kernel/k_thread.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-31 12:21:34 -04:00
										 |  |  | #include "core/hle/kernel/kernel.h"
 | 
					
						
							| 
									
										
										
										
											2022-10-15 21:57:40 -04:00
										 |  |  | #include "core/hle/kernel/service_thread.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  | #include "core/memory.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace Kernel { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-30 21:13:53 -07:00
										 |  |  | SessionRequestHandler::SessionRequestHandler(KernelCore& kernel_, const char* service_name_, | 
					
						
							|  |  |  |                                              ServiceThreadType thread_type) | 
					
						
							| 
									
										
										
										
											2022-11-06 19:43:38 -05:00
										 |  |  |     : kernel{kernel_}, service_thread{thread_type == ServiceThreadType::CreateNew | 
					
						
							|  |  |  |                                           ? kernel.CreateServiceThread(service_name_) | 
					
						
							|  |  |  |                                           : kernel.GetDefaultServiceThread()} {} | 
					
						
							| 
									
										
										
										
											2018-12-31 18:09:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-04 19:26:48 -07:00
										 |  |  | SessionRequestHandler::~SessionRequestHandler() { | 
					
						
							| 
									
										
										
										
											2022-11-06 19:43:38 -05:00
										 |  |  |     kernel.ReleaseServiceThread(service_thread); | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SessionRequestHandler::AcceptSession(KServerPort* server_port) { | 
					
						
							|  |  |  |     auto* server_session = server_port->AcceptSession(); | 
					
						
							|  |  |  |     ASSERT(server_session != nullptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RegisterSession(server_session, std::make_shared<SessionRequestManager>(kernel)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void SessionRequestHandler::RegisterSession(KServerSession* server_session, | 
					
						
							|  |  |  |                                             std::shared_ptr<SessionRequestManager> manager) { | 
					
						
							|  |  |  |     manager->SetSessionHandler(shared_from_this()); | 
					
						
							| 
									
										
										
										
											2022-11-06 19:43:38 -05:00
										 |  |  |     service_thread.RegisterServerSession(server_session, manager); | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |     server_session->Close(); | 
					
						
							| 
									
										
										
										
											2021-06-04 19:26:48 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | SessionRequestManager::SessionRequestManager(KernelCore& kernel_) : kernel{kernel_} {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-06 15:41:16 -07:00
										 |  |  | SessionRequestManager::~SessionRequestManager() = default; | 
					
						
							| 
									
										
										
										
											2018-12-31 18:09:41 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-07 21:55:37 -07:00
										 |  |  | bool SessionRequestManager::HasSessionRequestHandler(const HLERequestContext& context) const { | 
					
						
							|  |  |  |     if (IsDomain() && context.HasDomainMessageHeader()) { | 
					
						
							|  |  |  |         const auto& message_header = context.GetDomainMessageHeader(); | 
					
						
							|  |  |  |         const auto object_id = message_header.object_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (object_id > DomainHandlerCount()) { | 
					
						
							|  |  |  |             LOG_CRITICAL(IPC, "object_id {} is too big!", object_id); | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-04-06 17:36:19 -07:00
										 |  |  |         return !DomainHandler(object_id - 1).expired(); | 
					
						
							| 
									
										
										
										
											2021-06-07 21:55:37 -07:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         return session_handler != nullptr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-15 21:57:40 -04:00
										 |  |  | Result SessionRequestManager::CompleteSyncRequest(KServerSession* server_session, | 
					
						
							|  |  |  |                                                   HLERequestContext& context) { | 
					
						
							|  |  |  |     Result result = ResultSuccess; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // If the session has been converted to a domain, handle the domain request
 | 
					
						
							|  |  |  |     if (this->HasSessionRequestHandler(context)) { | 
					
						
							|  |  |  |         if (IsDomain() && context.HasDomainMessageHeader()) { | 
					
						
							|  |  |  |             result = HandleDomainSyncRequest(server_session, context); | 
					
						
							|  |  |  |             // If there is no domain header, the regular session handler is used
 | 
					
						
							|  |  |  |         } else if (this->HasSessionHandler()) { | 
					
						
							|  |  |  |             // If this manager has an associated HLE handler, forward the request to it.
 | 
					
						
							|  |  |  |             result = this->SessionHandler().HandleSyncRequest(*server_session, context); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ASSERT_MSG(false, "Session handler is invalid, stubbing response!"); | 
					
						
							|  |  |  |         IPC::ResponseBuilder rb(context, 2); | 
					
						
							|  |  |  |         rb.Push(ResultSuccess); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (convert_to_domain) { | 
					
						
							|  |  |  |         ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance."); | 
					
						
							|  |  |  |         this->ConvertToDomain(); | 
					
						
							|  |  |  |         convert_to_domain = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Result SessionRequestManager::HandleDomainSyncRequest(KServerSession* server_session, | 
					
						
							|  |  |  |                                                       HLERequestContext& context) { | 
					
						
							|  |  |  |     if (!context.HasDomainMessageHeader()) { | 
					
						
							|  |  |  |         return ResultSuccess; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
 | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |     ASSERT(context.GetManager().get() == this); | 
					
						
							| 
									
										
										
										
											2022-10-15 21:57:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // If there is a DomainMessageHeader, then this is CommandType "Request"
 | 
					
						
							|  |  |  |     const auto& domain_message_header = context.GetDomainMessageHeader(); | 
					
						
							|  |  |  |     const u32 object_id{domain_message_header.object_id}; | 
					
						
							|  |  |  |     switch (domain_message_header.command) { | 
					
						
							|  |  |  |     case IPC::DomainMessageHeader::CommandType::SendMessage: | 
					
						
							|  |  |  |         if (object_id > this->DomainHandlerCount()) { | 
					
						
							|  |  |  |             LOG_CRITICAL(IPC, | 
					
						
							|  |  |  |                          "object_id {} is too big! This probably means a recent service call " | 
					
						
							|  |  |  |                          "needed to return a new interface!", | 
					
						
							|  |  |  |                          object_id); | 
					
						
							|  |  |  |             ASSERT(false); | 
					
						
							|  |  |  |             return ResultSuccess; // Ignore error if asserts are off
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (auto strong_ptr = this->DomainHandler(object_id - 1).lock()) { | 
					
						
							|  |  |  |             return strong_ptr->HandleSyncRequest(*server_session, context); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ASSERT(false); | 
					
						
							|  |  |  |             return ResultSuccess; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: { | 
					
						
							|  |  |  |         LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this->CloseDomainHandler(object_id - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         IPC::ResponseBuilder rb{context, 2}; | 
					
						
							|  |  |  |         rb.Push(ResultSuccess); | 
					
						
							|  |  |  |         return ResultSuccess; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     LOG_CRITICAL(IPC, "Unknown domain command={}", domain_message_header.command.Value()); | 
					
						
							|  |  |  |     ASSERT(false); | 
					
						
							|  |  |  |     return ResultSuccess; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-02 18:02:10 -07:00
										 |  |  | HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_, | 
					
						
							| 
									
										
										
										
											2021-04-13 17:48:37 -07:00
										 |  |  |                                      KServerSession* server_session_, KThread* thread_) | 
					
						
							|  |  |  |     : server_session(server_session_), thread(thread_), kernel{kernel_}, memory{memory_} { | 
					
						
							| 
									
										
										
										
											2017-06-18 16:05:12 -07:00
										 |  |  |     cmd_buf[0] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-06 21:20:52 -07:00
										 |  |  | HLERequestContext::~HLERequestContext() = default; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-24 02:40:31 -07:00
										 |  |  | void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32_le* src_cmdbuf, | 
					
						
							| 
									
										
										
										
											2018-10-20 14:34:41 -04:00
										 |  |  |                                            bool incoming) { | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     IPC::RequestParser rp(src_cmdbuf); | 
					
						
							| 
									
										
										
										
											2019-03-07 16:44:28 -05:00
										 |  |  |     command_header = rp.PopRaw<IPC::CommandHeader>(); | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     if (command_header->IsCloseCommand()) { | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  |         // Close does not populate the rest of the IPC header
 | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     // If handle descriptor is present, add size of it
 | 
					
						
							|  |  |  |     if (command_header->enable_handle_descriptor) { | 
					
						
							| 
									
										
										
										
											2019-03-07 16:44:28 -05:00
										 |  |  |         handle_descriptor_header = rp.PopRaw<IPC::HandleDescriptorHeader>(); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |         if (handle_descriptor_header->send_current_pid) { | 
					
						
							| 
									
										
										
										
											2021-05-16 00:40:19 -04:00
										 |  |  |             pid = rp.Pop<u64>(); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-07 09:22:20 -05:00
										 |  |  |         if (incoming) { | 
					
						
							|  |  |  |             // Populate the object lists with the data in the IPC request.
 | 
					
						
							| 
									
										
										
										
											2022-12-15 22:30:42 -05:00
										 |  |  |             incoming_copy_handles.reserve(handle_descriptor_header->num_handles_to_copy); | 
					
						
							|  |  |  |             incoming_move_handles.reserve(handle_descriptor_header->num_handles_to_move); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 09:22:20 -05:00
										 |  |  |             for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { | 
					
						
							| 
									
										
										
										
											2021-05-18 19:52:52 -07:00
										 |  |  |                 incoming_copy_handles.push_back(rp.Pop<Handle>()); | 
					
						
							| 
									
										
										
										
											2018-01-07 09:22:20 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |             for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { | 
					
						
							| 
									
										
										
										
											2021-05-18 19:52:52 -07:00
										 |  |  |                 incoming_move_handles.push_back(rp.Pop<Handle>()); | 
					
						
							| 
									
										
										
										
											2018-01-07 09:22:20 -05:00
										 |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             // For responses we just ignore the handles, they're empty and will be populated when
 | 
					
						
							|  |  |  |             // translating the response.
 | 
					
						
							|  |  |  |             rp.Skip(handle_descriptor_header->num_handles_to_copy, false); | 
					
						
							|  |  |  |             rp.Skip(handle_descriptor_header->num_handles_to_move, false); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-15 22:30:42 -05:00
										 |  |  |     buffer_x_desciptors.reserve(command_header->num_buf_x_descriptors); | 
					
						
							|  |  |  |     buffer_a_desciptors.reserve(command_header->num_buf_a_descriptors); | 
					
						
							|  |  |  |     buffer_b_desciptors.reserve(command_header->num_buf_b_descriptors); | 
					
						
							|  |  |  |     buffer_w_desciptors.reserve(command_header->num_buf_w_descriptors); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |     for (u32 i = 0; i < command_header->num_buf_x_descriptors; ++i) { | 
					
						
							| 
									
										
										
										
											2017-10-18 21:38:01 -04:00
										 |  |  |         buffer_x_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorX>()); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |     for (u32 i = 0; i < command_header->num_buf_a_descriptors; ++i) { | 
					
						
							| 
									
										
										
										
											2017-10-18 21:38:01 -04:00
										 |  |  |         buffer_a_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |     for (u32 i = 0; i < command_header->num_buf_b_descriptors; ++i) { | 
					
						
							| 
									
										
										
										
											2017-10-18 21:38:01 -04:00
										 |  |  |         buffer_b_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |     for (u32 i = 0; i < command_header->num_buf_w_descriptors; ++i) { | 
					
						
							| 
									
										
										
										
											2017-10-18 21:38:01 -04:00
										 |  |  |         buffer_w_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorABW>()); | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-01-18 16:54:34 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 02:50:47 -07:00
										 |  |  |     const auto buffer_c_offset = rp.GetCurrentOffset() + command_header->data_size; | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     if (!command_header->IsTipc()) { | 
					
						
							|  |  |  |         // Padding to align to 16 bytes
 | 
					
						
							|  |  |  |         rp.AlignWithPadding(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |         if (GetManager()->IsDomain() && | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |             ((command_header->type == IPC::CommandType::Request || | 
					
						
							|  |  |  |               command_header->type == IPC::CommandType::RequestWithContext) || | 
					
						
							|  |  |  |              !incoming)) { | 
					
						
							|  |  |  |             // If this is an incoming message, only CommandType "Request" has a domain header
 | 
					
						
							|  |  |  |             // All outgoing domain messages have the domain header, if only incoming has it
 | 
					
						
							|  |  |  |             if (incoming || domain_message_header) { | 
					
						
							|  |  |  |                 domain_message_header = rp.PopRaw<IPC::DomainMessageHeader>(); | 
					
						
							|  |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |                 if (GetManager()->IsDomain()) { | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |                     LOG_WARNING(IPC, "Domain request has no DomainMessageHeader!"); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2019-03-07 16:44:28 -05:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2018-02-20 19:27:49 +03:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         data_payload_header = rp.PopRaw<IPC::DataPayloadHeader>(); | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         data_payload_offset = rp.GetCurrentOffset(); | 
					
						
							| 
									
										
										
										
											2018-01-17 01:16:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         if (domain_message_header && | 
					
						
							|  |  |  |             domain_message_header->command == | 
					
						
							|  |  |  |                 IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) { | 
					
						
							|  |  |  |             // CloseVirtualHandle command does not have SFC* or any data
 | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2018-01-17 01:16:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         if (incoming) { | 
					
						
							|  |  |  |             ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I')); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O')); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2017-10-15 01:24:22 -04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-18 16:54:34 -03:00
										 |  |  |     rp.SetCurrentOffset(buffer_c_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // For Inline buffers, the response data is written directly to buffer_c_offset
 | 
					
						
							|  |  |  |     // and in this case we don't have any BufferDescriptorC on the request.
 | 
					
						
							|  |  |  |     if (command_header->buf_c_descriptor_flags > | 
					
						
							|  |  |  |         IPC::CommandHeader::BufferDescriptorCFlag::InlineDescriptor) { | 
					
						
							|  |  |  |         if (command_header->buf_c_descriptor_flags == | 
					
						
							|  |  |  |             IPC::CommandHeader::BufferDescriptorCFlag::OneDescriptor) { | 
					
						
							|  |  |  |             buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |             u32 num_buf_c_descriptors = | 
					
						
							|  |  |  |                 static_cast<u32>(command_header->buf_c_descriptor_flags.Value()) - 2; | 
					
						
							| 
									
										
										
										
											2018-01-18 16:54:34 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // This is used to detect possible underflows, in case something is broken
 | 
					
						
							|  |  |  |             // with the two ifs above and the flags value is == 0 || == 1.
 | 
					
						
							|  |  |  |             ASSERT(num_buf_c_descriptors < 14); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-16 00:42:10 -04:00
										 |  |  |             for (u32 i = 0; i < num_buf_c_descriptors; ++i) { | 
					
						
							| 
									
										
										
										
											2018-01-18 16:54:34 -03:00
										 |  |  |                 buffer_c_desciptors.push_back(rp.PopRaw<IPC::BufferDescriptorC>()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     rp.SetCurrentOffset(data_payload_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  |     command = rp.Pop<u32_le>(); | 
					
						
							| 
									
										
										
										
											2018-01-06 23:19:42 -05:00
										 |  |  |     rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
 | 
					
						
							| 
									
										
										
										
											2017-10-14 22:18:42 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-25 22:44:19 -05:00
										 |  |  | Result HLERequestContext::PopulateFromIncomingCommandBuffer(const KHandleTable& handle_table, | 
					
						
							|  |  |  |                                                             u32_le* src_cmdbuf) { | 
					
						
							| 
									
										
										
										
											2018-10-20 14:34:41 -04:00
										 |  |  |     ParseCommandBuffer(handle_table, src_cmdbuf, true); | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (command_header->IsCloseCommand()) { | 
					
						
							| 
									
										
										
										
											2018-01-07 01:59:31 -05:00
										 |  |  |         // Close does not populate the rest of the IPC header
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |         return ResultSuccess; | 
					
						
							| 
									
										
										
										
											2018-01-07 01:59:31 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     std::copy_n(src_cmdbuf, IPC::COMMAND_BUFFER_LENGTH, cmd_buf.begin()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     return ResultSuccess; | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-25 22:44:19 -05:00
										 |  |  | Result HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_thread) { | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     auto current_offset = handles_offset; | 
					
						
							| 
									
										
										
										
											2021-05-08 12:11:36 -04:00
										 |  |  |     auto& owner_process = *requesting_thread.GetOwnerProcess(); | 
					
						
							| 
									
										
										
										
											2018-10-20 14:34:41 -04:00
										 |  |  |     auto& handle_table = owner_process.GetHandleTable(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-18 19:52:52 -07:00
										 |  |  |     for (auto& object : outgoing_copy_objects) { | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         Handle handle{}; | 
					
						
							|  |  |  |         if (object) { | 
					
						
							|  |  |  |             R_TRY(handle_table.Add(&handle, object)); | 
					
						
							| 
									
										
										
										
											2018-01-07 01:50:55 -05:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         cmd_buf[current_offset++] = handle; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2021-05-18 19:52:52 -07:00
										 |  |  |     for (auto& object : outgoing_move_objects) { | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         Handle handle{}; | 
					
						
							|  |  |  |         if (object) { | 
					
						
							|  |  |  |             R_TRY(handle_table.Add(&handle, object)); | 
					
						
							| 
									
										
										
										
											2018-01-07 01:50:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |             // Close our reference to the object, as it is being moved to the caller.
 | 
					
						
							|  |  |  |             object->Close(); | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |         cmd_buf[current_offset++] = handle; | 
					
						
							| 
									
										
										
										
											2017-06-09 05:23:13 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     // Write the domain objects to the command buffer, these go after the raw untranslated data.
 | 
					
						
							|  |  |  |     // TODO(Subv): This completely ignores C buffers.
 | 
					
						
							| 
									
										
										
										
											2018-01-07 01:50:55 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |     if (GetManager()->IsDomain()) { | 
					
						
							| 
									
										
										
										
											2021-05-18 19:52:52 -07:00
										 |  |  |         current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); | 
					
						
							| 
									
										
										
										
											2022-10-15 21:57:40 -04:00
										 |  |  |         for (auto& object : outgoing_domain_objects) { | 
					
						
							| 
									
										
										
										
											2022-10-16 01:53:56 -04:00
										 |  |  |             GetManager()->AppendDomainHandler(std::move(object)); | 
					
						
							|  |  |  |             cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount()); | 
					
						
							| 
									
										
										
										
											2018-01-07 01:50:55 -05:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-18 20:17:06 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Copy the translated command buffer back into the thread's command buffer area.
 | 
					
						
							| 
									
										
										
										
											2021-05-10 16:16:36 -07:00
										 |  |  |     memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(), | 
					
						
							| 
									
										
										
										
											2021-05-15 23:49:03 -07:00
										 |  |  |                       write_size * sizeof(u32)); | 
					
						
							| 
									
										
										
										
											2018-03-18 20:17:06 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-21 01:05:04 -04:00
										 |  |  |     return ResultSuccess; | 
					
						
							| 
									
										
										
										
											2017-06-08 23:55:18 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 22:02:08 -04:00
										 |  |  | std::vector<u8> HLERequestContext::ReadBuffer(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |                            BufferDescriptorA()[buffer_index].Size()}; | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     if (is_buffer_a) { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |             BufferDescriptorA().size() > buffer_index, { return {}; }, | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |             "BufferDescriptorA invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |         std::vector<u8> buffer(BufferDescriptorA()[buffer_index].Size()); | 
					
						
							| 
									
										
										
										
											2019-11-26 16:29:34 -05:00
										 |  |  |         memory.ReadBlock(BufferDescriptorA()[buffer_index].Address(), buffer.data(), buffer.size()); | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |         return buffer; | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |             BufferDescriptorX().size() > buffer_index, { return {}; }, | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |             "BufferDescriptorX invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |         std::vector<u8> buffer(BufferDescriptorX()[buffer_index].Size()); | 
					
						
							| 
									
										
										
										
											2019-11-26 16:29:34 -05:00
										 |  |  |         memory.ReadBlock(BufferDescriptorX()[buffer_index].Address(), buffer.data(), buffer.size()); | 
					
						
							| 
									
										
										
										
											2022-12-15 23:22:11 -05:00
										 |  |  |         return buffer; | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-25 13:20:59 -05:00
										 |  |  | std::span<const u8> HLERequestContext::ReadBufferSpan(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 
					
						
							|  |  |  |                            BufferDescriptorA()[buffer_index].Size()}; | 
					
						
							|  |  |  |     if (is_buffer_a) { | 
					
						
							|  |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorA().size() > buffer_index, { return {}; }, | 
					
						
							|  |  |  |             "BufferDescriptorA invalid buffer_index {}", buffer_index); | 
					
						
							|  |  |  |         const u8* const mem_ptr = memory.GetPointer(BufferDescriptorA()[buffer_index].Address()); | 
					
						
							|  |  |  |         return std::span<const u8>(mem_ptr, BufferDescriptorA()[buffer_index].Size()); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorX().size() > buffer_index, { return {}; }, | 
					
						
							|  |  |  |             "BufferDescriptorX invalid buffer_index {}", buffer_index); | 
					
						
							|  |  |  |         const u8* const mem_ptr = memory.GetPointer(BufferDescriptorX()[buffer_index].Address()); | 
					
						
							|  |  |  |         return std::span<const u8>(mem_ptr, BufferDescriptorX()[buffer_index].Size()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-15 15:21:06 +02:00
										 |  |  | std::size_t HLERequestContext::WriteBuffer(const void* buffer, std::size_t size, | 
					
						
							| 
									
										
										
										
											2020-04-16 22:02:08 -04:00
										 |  |  |                                            std::size_t buffer_index) const { | 
					
						
							| 
									
										
										
										
											2018-06-22 11:18:23 +03:00
										 |  |  |     if (size == 0) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_WARNING(Core, "skip empty buffer write"); | 
					
						
							| 
									
										
										
										
											2018-06-22 11:18:23 +03:00
										 |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 22:02:08 -04:00
										 |  |  |     const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |                            BufferDescriptorB()[buffer_index].Size()}; | 
					
						
							| 
									
										
										
										
											2018-09-15 15:21:06 +02:00
										 |  |  |     const std::size_t buffer_size{GetWriteBufferSize(buffer_index)}; | 
					
						
							| 
									
										
										
										
											2018-03-31 16:05:19 -04:00
										 |  |  |     if (size > buffer_size) { | 
					
						
							| 
									
										
										
										
											2018-07-02 10:13:26 -06:00
										 |  |  |         LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, | 
					
						
							| 
									
										
										
										
											2018-07-02 10:20:50 -06:00
										 |  |  |                      buffer_size); | 
					
						
							| 
									
										
										
										
											2018-03-31 16:05:19 -04:00
										 |  |  |         size = buffer_size; // TODO(bunnei): This needs to be HW tested
 | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-14 00:14:17 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     if (is_buffer_b) { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorB().size() > buffer_index && | 
					
						
							|  |  |  |                 BufferDescriptorB()[buffer_index].Size() >= size, | 
					
						
							|  |  |  |             { return 0; }, "BufferDescriptorB is invalid, index={}, size={}", buffer_index, size); | 
					
						
							| 
									
										
										
										
											2022-07-16 23:48:45 +01:00
										 |  |  |         WriteBufferB(buffer, size, buffer_index); | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorC().size() > buffer_index && | 
					
						
							|  |  |  |                 BufferDescriptorC()[buffer_index].Size() >= size, | 
					
						
							|  |  |  |             { return 0; }, "BufferDescriptorC is invalid, index={}, size={}", buffer_index, size); | 
					
						
							| 
									
										
										
										
											2022-07-16 23:48:45 +01:00
										 |  |  |         WriteBufferC(buffer, size, buffer_index); | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-13 23:53:18 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return size; | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-16 23:48:45 +01:00
										 |  |  | std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size, | 
					
						
							|  |  |  |                                             std::size_t buffer_index) const { | 
					
						
							|  |  |  |     if (buffer_index >= BufferDescriptorB().size() || size == 0) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto buffer_size{BufferDescriptorB()[buffer_index].Size()}; | 
					
						
							|  |  |  |     if (size > buffer_size) { | 
					
						
							|  |  |  |         LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, | 
					
						
							|  |  |  |                      buffer_size); | 
					
						
							|  |  |  |         size = buffer_size; // TODO(bunnei): This needs to be HW tested
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); | 
					
						
							|  |  |  |     return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::size_t HLERequestContext::WriteBufferC(const void* buffer, std::size_t size, | 
					
						
							|  |  |  |                                             std::size_t buffer_index) const { | 
					
						
							|  |  |  |     if (buffer_index >= BufferDescriptorC().size() || size == 0) { | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const auto buffer_size{BufferDescriptorC()[buffer_index].Size()}; | 
					
						
							|  |  |  |     if (size > buffer_size) { | 
					
						
							|  |  |  |         LOG_CRITICAL(Core, "size ({:016X}) is greater than buffer_size ({:016X})", size, | 
					
						
							|  |  |  |                      buffer_size); | 
					
						
							|  |  |  |         size = buffer_size; // TODO(bunnei): This needs to be HW tested
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); | 
					
						
							|  |  |  |     return size; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 22:02:08 -04:00
										 |  |  | std::size_t HLERequestContext::GetReadBufferSize(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |                            BufferDescriptorA()[buffer_index].Size()}; | 
					
						
							|  |  |  |     if (is_buffer_a) { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorA().size() > buffer_index, { return 0; }, | 
					
						
							|  |  |  |             "BufferDescriptorA invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |         return BufferDescriptorA()[buffer_index].Size(); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorX().size() > buffer_index, { return 0; }, | 
					
						
							|  |  |  |             "BufferDescriptorX invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |         return BufferDescriptorX()[buffer_index].Size(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-14 00:14:17 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-16 22:02:08 -04:00
										 |  |  | std::size_t HLERequestContext::GetWriteBufferSize(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |                            BufferDescriptorB()[buffer_index].Size()}; | 
					
						
							|  |  |  |     if (is_buffer_b) { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorB().size() > buffer_index, { return 0; }, | 
					
						
							|  |  |  |             "BufferDescriptorB invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |         return BufferDescriptorB()[buffer_index].Size(); | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2020-08-11 11:08:10 -04:00
										 |  |  |         ASSERT_OR_EXECUTE_MSG( | 
					
						
							|  |  |  |             BufferDescriptorC().size() > buffer_index, { return 0; }, | 
					
						
							|  |  |  |             "BufferDescriptorC invalid buffer_index {}", buffer_index); | 
					
						
							| 
									
										
										
										
											2020-02-05 22:09:16 -05:00
										 |  |  |         return BufferDescriptorC()[buffer_index].Size(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-06-24 22:50:27 +10:00
										 |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2018-02-13 21:41:20 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-28 01:18:06 -05:00
										 |  |  | bool HLERequestContext::CanReadBuffer(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_a{BufferDescriptorA().size() > buffer_index && | 
					
						
							|  |  |  |                            BufferDescriptorA()[buffer_index].Size()}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_buffer_a) { | 
					
						
							|  |  |  |         return BufferDescriptorA().size() > buffer_index; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return BufferDescriptorX().size() > buffer_index; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool HLERequestContext::CanWriteBuffer(std::size_t buffer_index) const { | 
					
						
							|  |  |  |     const bool is_buffer_b{BufferDescriptorB().size() > buffer_index && | 
					
						
							|  |  |  |                            BufferDescriptorB()[buffer_index].Size()}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (is_buffer_b) { | 
					
						
							|  |  |  |         return BufferDescriptorB().size() > buffer_index; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return BufferDescriptorC().size() > buffer_index; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-15 17:22:11 +03:00
										 |  |  | std::string HLERequestContext::Description() const { | 
					
						
							|  |  |  |     if (!command_header) { | 
					
						
							|  |  |  |         return "No command header available"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     std::ostringstream s; | 
					
						
							|  |  |  |     s << "IPC::CommandHeader: Type:" << static_cast<u32>(command_header->type.Value()); | 
					
						
							|  |  |  |     s << ", X(Pointer):" << command_header->num_buf_x_descriptors; | 
					
						
							|  |  |  |     if (command_header->num_buf_x_descriptors) { | 
					
						
							|  |  |  |         s << '['; | 
					
						
							|  |  |  |         for (u64 i = 0; i < command_header->num_buf_x_descriptors; ++i) { | 
					
						
							|  |  |  |             s << "0x" << std::hex << BufferDescriptorX()[i].Size(); | 
					
						
							|  |  |  |             if (i < command_header->num_buf_x_descriptors - 1) | 
					
						
							|  |  |  |                 s << ", "; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s << ']'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s << ", A(Send):" << command_header->num_buf_a_descriptors; | 
					
						
							|  |  |  |     if (command_header->num_buf_a_descriptors) { | 
					
						
							|  |  |  |         s << '['; | 
					
						
							|  |  |  |         for (u64 i = 0; i < command_header->num_buf_a_descriptors; ++i) { | 
					
						
							|  |  |  |             s << "0x" << std::hex << BufferDescriptorA()[i].Size(); | 
					
						
							|  |  |  |             if (i < command_header->num_buf_a_descriptors - 1) | 
					
						
							|  |  |  |                 s << ", "; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s << ']'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s << ", B(Receive):" << command_header->num_buf_b_descriptors; | 
					
						
							|  |  |  |     if (command_header->num_buf_b_descriptors) { | 
					
						
							|  |  |  |         s << '['; | 
					
						
							|  |  |  |         for (u64 i = 0; i < command_header->num_buf_b_descriptors; ++i) { | 
					
						
							|  |  |  |             s << "0x" << std::hex << BufferDescriptorB()[i].Size(); | 
					
						
							|  |  |  |             if (i < command_header->num_buf_b_descriptors - 1) | 
					
						
							|  |  |  |                 s << ", "; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s << ']'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s << ", C(ReceiveList):" << BufferDescriptorC().size(); | 
					
						
							|  |  |  |     if (!BufferDescriptorC().empty()) { | 
					
						
							|  |  |  |         s << '['; | 
					
						
							|  |  |  |         for (u64 i = 0; i < BufferDescriptorC().size(); ++i) { | 
					
						
							|  |  |  |             s << "0x" << std::hex << BufferDescriptorC()[i].Size(); | 
					
						
							|  |  |  |             if (i < BufferDescriptorC().size() - 1) | 
					
						
							|  |  |  |                 s << ", "; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         s << ']'; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s << ", data_size:" << command_header->data_size.Value(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return s.str(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-04 21:52:19 -07:00
										 |  |  | } // namespace Kernel
 |