mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #3077 from Subv/hle_static_buffer
Kernel/IPC: Implement StaticBuffer translation for HLE services that use the HLERequestContext architecture.
This commit is contained in:
		
						commit
						555c8ba7c1
					
				
					 11 changed files with 182 additions and 45 deletions
				
			
		|  | @ -40,13 +40,16 @@ static const int kStaticBuffersOffset = 0x100; | ||||||
| inline u32* GetStaticBuffers(const int offset = 0) { | inline u32* GetStaticBuffers(const int offset = 0) { | ||||||
|     return GetCommandBuffer(kStaticBuffersOffset + offset); |     return GetCommandBuffer(kStaticBuffersOffset + offset); | ||||||
| } | } | ||||||
| } | } // namespace Kernel
 | ||||||
| 
 | 
 | ||||||
| namespace IPC { | namespace IPC { | ||||||
| 
 | 
 | ||||||
| /// Size of the command buffer area, in 32-bit words.
 | /// Size of the command buffer area, in 32-bit words.
 | ||||||
| constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); | constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32); | ||||||
| 
 | 
 | ||||||
|  | // Maximum number of static buffers per thread.
 | ||||||
|  | constexpr size_t MAX_STATIC_BUFFERS = 16; | ||||||
|  | 
 | ||||||
| // These errors are commonly returned by invalid IPC translations, so alias them here for
 | // These errors are commonly returned by invalid IPC translations, so alias them here for
 | ||||||
| // convenience.
 | // convenience.
 | ||||||
| // TODO(yuriks): These will probably go away once translation is implemented inside the kernel.
 | // TODO(yuriks): These will probably go away once translation is implemented inside the kernel.
 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include <tuple> | #include <tuple> | ||||||
| #include <type_traits> | #include <type_traits> | ||||||
| #include <utility> | #include <utility> | ||||||
|  | #include <vector> | ||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
| #include "core/hle/kernel/handle_table.h" | #include "core/hle/kernel/handle_table.h" | ||||||
| #include "core/hle/kernel/hle_ipc.h" | #include "core/hle/kernel/hle_ipc.h" | ||||||
|  | @ -117,7 +118,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void PushCurrentPIDHandle(); |     void PushCurrentPIDHandle(); | ||||||
| 
 | 
 | ||||||
|     void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); |     [[deprecated]] void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); | ||||||
|  |     void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id); | ||||||
| 
 | 
 | ||||||
|     void PushMappedBuffer(VAddr buffer_vaddr, size_t size, MappedBufferPermissions perms); |     void PushMappedBuffer(VAddr buffer_vaddr, size_t size, MappedBufferPermissions perms); | ||||||
| }; | }; | ||||||
|  | @ -195,6 +197,16 @@ inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 | ||||||
|     Push(buffer_vaddr); |     Push(buffer_vaddr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | inline void RequestBuilder::PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id) { | ||||||
|  |     ASSERT_MSG(buffer_id < MAX_STATIC_BUFFERS, "Invalid static buffer id"); | ||||||
|  | 
 | ||||||
|  |     Push(StaticBufferDesc(buffer.size(), buffer_id)); | ||||||
|  |     // This address will be replaced by the correct static buffer address during IPC translation.
 | ||||||
|  |     Push<VAddr>(0xDEADC0DE); | ||||||
|  | 
 | ||||||
|  |     context->AddStaticBuffer(buffer_id, buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size, | inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size, | ||||||
|                                              MappedBufferPermissions perms) { |                                              MappedBufferPermissions perms) { | ||||||
|     Push(MappedBufferDesc(size, perms)); |     Push(MappedBufferDesc(size, perms)); | ||||||
|  | @ -295,17 +307,23 @@ public: | ||||||
|      * @brief Pops the static buffer vaddr |      * @brief Pops the static buffer vaddr | ||||||
|      * @return                  The virtual address of the buffer |      * @return                  The virtual address of the buffer | ||||||
|      * @param[out] data_size    If non-null, the pointed value will be set to the size of the data |      * @param[out] data_size    If non-null, the pointed value will be set to the size of the data | ||||||
|      * @param[out] useStaticBuffersToGetVaddr Indicates if we should read the vaddr from the static |  | ||||||
|      * buffers (which is the correct thing to do, but no service presently implement it) instead of |  | ||||||
|      * using the same value as the process who sent the request |  | ||||||
|      * given by the source process |  | ||||||
|      * |      * | ||||||
|      * Static buffers must be set up before any IPC request using those is sent. |      * In real services, static buffers must be set up before any IPC request using those is sent. | ||||||
|      * It is the duty of the process (usually services) to allocate and set up the receiving static |      * It is the duty of the process (usually services) to allocate and set up the receiving static | ||||||
|      * buffer information |      * buffer information. Our HLE services do not need to set up the buffers beforehand. | ||||||
|      * Please note that the setup uses virtual addresses. |      * Please note that the setup uses virtual addresses. | ||||||
|      */ |      */ | ||||||
|     VAddr PopStaticBuffer(size_t* data_size = nullptr, bool useStaticBuffersToGetVaddr = false); |     [[deprecated]] VAddr PopStaticBuffer(size_t* data_size); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * @brief Pops a static buffer from the IPC request buffer. | ||||||
|  |      * @return The buffer that was copied from the IPC request originator. | ||||||
|  |      * | ||||||
|  |      * In real services, static buffers must be set up before any IPC request using those is sent. | ||||||
|  |      * It is the duty of the process (usually services) to allocate and set up the receiving static | ||||||
|  |      * buffer information. Our HLE services do not need to set up the buffers beforehand. | ||||||
|  |      */ | ||||||
|  |     const std::vector<u8>& PopStaticBuffer(); | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * @brief Pops the mapped buffer vaddr |      * @brief Pops the mapped buffer vaddr | ||||||
|  | @ -451,21 +469,21 @@ inline std::tuple<Kernel::SharedPtr<T>...> RequestParser::PopObjects() { | ||||||
|                                           std::index_sequence_for<T...>{}); |                                           std::index_sequence_for<T...>{}); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline VAddr RequestParser::PopStaticBuffer(size_t* data_size, bool useStaticBuffersToGetVaddr) { | inline VAddr RequestParser::PopStaticBuffer(size_t* data_size) { | ||||||
|     const u32 sbuffer_descriptor = Pop<u32>(); |     const u32 sbuffer_descriptor = Pop<u32>(); | ||||||
|     StaticBufferDescInfo bufferInfo{sbuffer_descriptor}; |     StaticBufferDescInfo bufferInfo{sbuffer_descriptor}; | ||||||
|     if (data_size != nullptr) |     if (data_size != nullptr) | ||||||
|         *data_size = bufferInfo.size; |         *data_size = bufferInfo.size; | ||||||
|     if (!useStaticBuffersToGetVaddr) |  | ||||||
|     return Pop<VAddr>(); |     return Pop<VAddr>(); | ||||||
|     else { |  | ||||||
|         ASSERT_MSG(0, "remove the assert if multiprocess/IPC translation are implemented."); |  | ||||||
|         // The buffer has already been copied to the static buffer by the kernel during
 |  | ||||||
|         // translation
 |  | ||||||
|         Pop<VAddr>(); // Pop the calling process buffer address
 |  | ||||||
|                       // and get the vaddr from the static buffers
 |  | ||||||
|         return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1]; |  | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | inline const std::vector<u8>& RequestParser::PopStaticBuffer() { | ||||||
|  |     const u32 sbuffer_descriptor = Pop<u32>(); | ||||||
|  |     // Pop the address from the incoming request buffer
 | ||||||
|  |     Pop<VAddr>(); | ||||||
|  | 
 | ||||||
|  |     StaticBufferDescInfo buffer_info{sbuffer_descriptor}; | ||||||
|  |     return context->GetStaticBuffer(buffer_info.buffer_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline VAddr RequestParser::PopMappedBuffer(size_t* data_size, | inline VAddr RequestParser::PopMappedBuffer(size_t* data_size, | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <vector> | ||||||
| #include <boost/range/algorithm_ext/erase.hpp> | #include <boost/range/algorithm_ext/erase.hpp> | ||||||
| #include "common/assert.h" | #include "common/assert.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  | @ -44,6 +45,16 @@ void HLERequestContext::ClearIncomingObjects() { | ||||||
|     request_handles.clear(); |     request_handles.clear(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | const std::vector<u8>& HLERequestContext::GetStaticBuffer(u8 buffer_id) const { | ||||||
|  |     ASSERT_MSG(!static_buffers[buffer_id].empty(), "Empty static buffer!"); | ||||||
|  |     return static_buffers[buffer_id]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HLERequestContext::AddStaticBuffer(u8 buffer_id, std::vector<u8> data) { | ||||||
|  |     ASSERT(static_buffers[buffer_id].empty() && !data.empty()); | ||||||
|  |     static_buffers[buffer_id] = std::move(data); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, | ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, | ||||||
|                                                                 Process& src_process, |                                                                 Process& src_process, | ||||||
|                                                                 HandleTable& src_table) { |                                                                 HandleTable& src_table) { | ||||||
|  | @ -84,6 +95,18 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr | ||||||
|             cmd_buf[i++] = src_process.process_id; |             cmd_buf[i++] = src_process.process_id; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |         case IPC::DescriptorType::StaticBuffer: { | ||||||
|  |             VAddr source_address = src_cmdbuf[i]; | ||||||
|  |             IPC::StaticBufferDescInfo buffer_info{descriptor}; | ||||||
|  | 
 | ||||||
|  |             // Copy the input buffer into our own vector and store it.
 | ||||||
|  |             std::vector<u8> data(buffer_info.size); | ||||||
|  |             Memory::ReadBlock(src_process, source_address, data.data(), data.size()); | ||||||
|  | 
 | ||||||
|  |             AddStaticBuffer(buffer_info.buffer_id, std::move(data)); | ||||||
|  |             cmd_buf[i++] = source_address; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         default: |         default: | ||||||
|             UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); |             UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); | ||||||
|         } |         } | ||||||
|  | @ -124,6 +147,25 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|  |         case IPC::DescriptorType::StaticBuffer: { | ||||||
|  |             IPC::StaticBufferDescInfo buffer_info{descriptor}; | ||||||
|  | 
 | ||||||
|  |             const auto& data = GetStaticBuffer(buffer_info.buffer_id); | ||||||
|  | 
 | ||||||
|  |             // Grab the address that the target thread set up to receive the response static buffer
 | ||||||
|  |             // and write our data there. The static buffers area is located right after the command
 | ||||||
|  |             // buffer area.
 | ||||||
|  |             size_t static_buffer_offset = IPC::COMMAND_BUFFER_LENGTH + 2 * buffer_info.buffer_id; | ||||||
|  |             IPC::StaticBufferDescInfo target_descriptor{dst_cmdbuf[static_buffer_offset]}; | ||||||
|  |             VAddr target_address = dst_cmdbuf[static_buffer_offset + 1]; | ||||||
|  | 
 | ||||||
|  |             ASSERT_MSG(target_descriptor.size >= data.size(), "Static buffer data is too big"); | ||||||
|  | 
 | ||||||
|  |             Memory::WriteBlock(dst_process, target_address, data.data(), data.size()); | ||||||
|  | 
 | ||||||
|  |             dst_cmdbuf[i++] = target_address; | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|         default: |         default: | ||||||
|             UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); |             UNIMPLEMENTED_MSG("Unsupported handle translation: 0x%08X", descriptor); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -119,6 +119,18 @@ public: | ||||||
|      */ |      */ | ||||||
|     void ClearIncomingObjects(); |     void ClearIncomingObjects(); | ||||||
| 
 | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Retrieves the static buffer identified by the input buffer_id. The static buffer *must* have | ||||||
|  |      * been created in PopulateFromIncomingCommandBuffer by way of an input StaticBuffer descriptor. | ||||||
|  |      */ | ||||||
|  |     const std::vector<u8>& GetStaticBuffer(u8 buffer_id) const; | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Sets up a static buffer that will be copied to the target process when the request is | ||||||
|  |      * translated. | ||||||
|  |      */ | ||||||
|  |     void AddStaticBuffer(u8 buffer_id, std::vector<u8> data); | ||||||
|  | 
 | ||||||
|     /// Populates this context with data from the requesting process/thread.
 |     /// Populates this context with data from the requesting process/thread.
 | ||||||
|     ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process, |     ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process, | ||||||
|                                                  HandleTable& src_table); |                                                  HandleTable& src_table); | ||||||
|  | @ -131,6 +143,8 @@ private: | ||||||
|     SharedPtr<ServerSession> session; |     SharedPtr<ServerSession> session; | ||||||
|     // TODO(yuriks): Check common usage of this and optimize size accordingly
 |     // TODO(yuriks): Check common usage of this and optimize size accordingly
 | ||||||
|     boost::container::small_vector<SharedPtr<Object>, 8> request_handles; |     boost::container::small_vector<SharedPtr<Object>, 8> request_handles; | ||||||
|  |     // The static buffers will be created when the IPC request is translated.
 | ||||||
|  |     std::array<std::vector<u8>, IPC::MAX_STATIC_BUFFERS> static_buffers; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace Kernel
 | } // namespace Kernel
 | ||||||
|  |  | ||||||
|  | @ -2,6 +2,7 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
|  | #include <vector> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
| #include "core/hle/ipc.h" | #include "core/hle/ipc.h" | ||||||
|  | @ -19,17 +20,12 @@ namespace AC { | ||||||
| void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { | void Module::Interface::CreateDefaultConfig(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x1, 0, 0); |     IPC::RequestParser rp(ctx, 0x1, 0, 0); | ||||||
| 
 | 
 | ||||||
|     std::size_t desc_size; |     std::vector<u8> buffer(sizeof(ACConfig)); | ||||||
|     VAddr ac_config_addr = rp.PeekStaticBuffer(0, &desc_size); |     std::memcpy(buffer.data(), &ac->default_config, buffer.size()); | ||||||
| 
 |  | ||||||
|     ASSERT_MSG(desc_size >= sizeof(Module::ACConfig), |  | ||||||
|                "Output buffer size can't fit ACConfig structure"); |  | ||||||
| 
 |  | ||||||
|     Memory::WriteBlock(ac_config_addr, &ac->default_config, sizeof(ACConfig)); |  | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushStaticBuffer(ac_config_addr, sizeof(ACConfig), 0); |     rb.PushStaticBuffer(std::move(buffer), 0); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_AC, "(STUBBED) called"); |     LOG_WARNING(Service_AC, "(STUBBED) called"); | ||||||
| } | } | ||||||
|  | @ -106,7 +102,7 @@ void Module::Interface::GetWifiStatus(Kernel::HLERequestContext& ctx) { | ||||||
| 
 | 
 | ||||||
| void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) { | void Module::Interface::GetInfraPriority(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(ctx, 0x27, 0, 2); |     IPC::RequestParser rp(ctx, 0x27, 0, 2); | ||||||
|     VAddr ac_config = rp.PopStaticBuffer(); |     const std::vector<u8>& ac_config = rp.PopStaticBuffer(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|  | @ -121,13 +117,13 @@ void Module::Interface::SetRequestEulaVersion(Kernel::HLERequestContext& ctx) { | ||||||
|     u32 major = rp.Pop<u8>(); |     u32 major = rp.Pop<u8>(); | ||||||
|     u32 minor = rp.Pop<u8>(); |     u32 minor = rp.Pop<u8>(); | ||||||
| 
 | 
 | ||||||
|     VAddr ac_config = rp.PopStaticBuffer(); |     const std::vector<u8>& ac_config = rp.PopStaticBuffer(); | ||||||
| 
 | 
 | ||||||
|     // TODO(Subv): Copy over the input ACConfig to the stored ACConfig.
 |     // TODO(Subv): Copy over the input ACConfig to the stored ACConfig.
 | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushStaticBuffer(ac_config, sizeof(ACConfig), 0); |     rb.PushStaticBuffer(std::move(ac_config), 0); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_AC, "(STUBBED) called, major=%u, minor=%u", major, minor); |     LOG_WARNING(Service_AC, "(STUBBED) called, major=%u, minor=%u", major, minor); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -720,7 +720,7 @@ void AppletUtility(Service::Interface* self) { | ||||||
|     u32 utility_command = rp.Pop<u32>(); |     u32 utility_command = rp.Pop<u32>(); | ||||||
|     u32 input_size = rp.Pop<u32>(); |     u32 input_size = rp.Pop<u32>(); | ||||||
|     u32 output_size = rp.Pop<u32>(); |     u32 output_size = rp.Pop<u32>(); | ||||||
|     VAddr input_addr = rp.PopStaticBuffer(); |     VAddr input_addr = rp.PopStaticBuffer(nullptr); | ||||||
| 
 | 
 | ||||||
|     VAddr output_addr = rp.PeekStaticBuffer(0); |     VAddr output_addr = rp.PeekStaticBuffer(0); | ||||||
| 
 | 
 | ||||||
|  | @ -823,7 +823,7 @@ void StartLibraryApplet(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     size_t buffer_size = rp.Pop<u32>(); |     size_t buffer_size = rp.Pop<u32>(); | ||||||
|     Kernel::Handle handle = rp.PopHandle(); |     Kernel::Handle handle = rp.PopHandle(); | ||||||
|     VAddr buffer_addr = rp.PopStaticBuffer(); |     VAddr buffer_addr = rp.PopStaticBuffer(nullptr); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_APT, "called applet_id=%08X", static_cast<u32>(applet_id)); |     LOG_DEBUG(Service_APT, "called applet_id=%08X", static_cast<u32>(applet_id)); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -113,7 +113,7 @@ void UnscrambleLocalFriendCode(Service::Interface* self) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1C, 1, 2); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1C, 1, 2); | ||||||
|     const u32 friend_code_count = rp.Pop<u32>(); |     const u32 friend_code_count = rp.Pop<u32>(); | ||||||
|     size_t in_buffer_size; |     size_t in_buffer_size; | ||||||
|     const VAddr scrambled_friend_codes = rp.PopStaticBuffer(&in_buffer_size, false); |     const VAddr scrambled_friend_codes = rp.PopStaticBuffer(&in_buffer_size); | ||||||
|     ASSERT_MSG(in_buffer_size == (friend_code_count * scrambled_friend_code_size), |     ASSERT_MSG(in_buffer_size == (friend_code_count * scrambled_friend_code_size), | ||||||
|                "Wrong input buffer size"); |                "Wrong input buffer size"); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -72,7 +72,7 @@ static void OpenFile(Service::Interface* self) { | ||||||
|     FileSys::Mode mode; |     FileSys::Mode mode; | ||||||
|     mode.hex = rp.Pop<u32>(); |     mode.hex = rp.Pop<u32>(); | ||||||
|     u32 attributes = rp.Pop<u32>(); // TODO(Link Mauve): do something with those attributes.
 |     u32 attributes = rp.Pop<u32>(); // TODO(Link Mauve): do something with those attributes.
 | ||||||
|     VAddr filename_ptr = rp.PopStaticBuffer(); |     VAddr filename_ptr = rp.PopStaticBuffer(nullptr); | ||||||
|     FileSys::Path file_path(filename_type, filename_size, filename_ptr); |     FileSys::Path file_path(filename_type, filename_size, filename_ptr); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex, |     LOG_DEBUG(Service_FS, "path=%s, mode=%u attrs=%u", file_path.DebugStr().c_str(), mode.hex, | ||||||
|  |  | ||||||
|  | @ -433,7 +433,7 @@ static void FinalizeIrNop(Interface* self) { | ||||||
| static void SendIrNop(Interface* self) { | static void SendIrNop(Interface* self) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 1, 2); |     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0D, 1, 2); | ||||||
|     const u32 size = rp.Pop<u32>(); |     const u32 size = rp.Pop<u32>(); | ||||||
|     const VAddr address = rp.PopStaticBuffer(); |     const VAddr address = rp.PopStaticBuffer(nullptr); | ||||||
| 
 | 
 | ||||||
|     std::vector<u8> buffer(size); |     std::vector<u8> buffer(size); | ||||||
|     Memory::ReadBlock(address, buffer.data(), size); |     Memory::ReadBlock(address, buffer.data(), size); | ||||||
|  |  | ||||||
|  | @ -771,9 +771,9 @@ static void BeginHostingNetwork(Interface* self) { | ||||||
|     const u32 passphrase_size = rp.Pop<u32>(); |     const u32 passphrase_size = rp.Pop<u32>(); | ||||||
| 
 | 
 | ||||||
|     size_t desc_size; |     size_t desc_size; | ||||||
|     const VAddr network_info_address = rp.PopStaticBuffer(&desc_size, false); |     const VAddr network_info_address = rp.PopStaticBuffer(&desc_size); | ||||||
|     ASSERT(desc_size == sizeof(NetworkInfo)); |     ASSERT(desc_size == sizeof(NetworkInfo)); | ||||||
|     const VAddr passphrase_address = rp.PopStaticBuffer(&desc_size, false); |     const VAddr passphrase_address = rp.PopStaticBuffer(&desc_size); | ||||||
|     ASSERT(desc_size == passphrase_size); |     ASSERT(desc_size == passphrase_size); | ||||||
| 
 | 
 | ||||||
|     // TODO(Subv): Store the passphrase and verify it when attempting a connection.
 |     // TODO(Subv): Store the passphrase and verify it when attempting a connection.
 | ||||||
|  | @ -907,7 +907,7 @@ static void SendTo(Interface* self) { | ||||||
|     u32 flags = rp.Pop<u32>(); |     u32 flags = rp.Pop<u32>(); | ||||||
| 
 | 
 | ||||||
|     size_t desc_size; |     size_t desc_size; | ||||||
|     const VAddr input_address = rp.PopStaticBuffer(&desc_size, false); |     const VAddr input_address = rp.PopStaticBuffer(&desc_size); | ||||||
|     ASSERT(desc_size >= data_size); |     ASSERT(desc_size >= data_size); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  | @ -1093,7 +1093,7 @@ static void SetApplicationData(Interface* self) { | ||||||
|     u32 size = rp.Pop<u32>(); |     u32 size = rp.Pop<u32>(); | ||||||
| 
 | 
 | ||||||
|     size_t desc_size; |     size_t desc_size; | ||||||
|     const VAddr address = rp.PopStaticBuffer(&desc_size, false); |     const VAddr address = rp.PopStaticBuffer(&desc_size); | ||||||
|     ASSERT(desc_size == size); |     ASSERT(desc_size == size); | ||||||
| 
 | 
 | ||||||
|     LOG_DEBUG(Service_NWM, "called"); |     LOG_DEBUG(Service_NWM, "called"); | ||||||
|  |  | ||||||
|  | @ -116,25 +116,58 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel | ||||||
|         REQUIRE(context.CommandBuffer()[2] == process->process_id); |         REQUIRE(context.CommandBuffer()[2] == process->process_id); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     SECTION("translates StaticBuffer descriptors") { | ||||||
|  |         auto buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||||
|  |         std::fill(buffer->begin(), buffer->end(), 0xAB); | ||||||
|  | 
 | ||||||
|  |         VAddr target_address = 0x10000000; | ||||||
|  |         auto result = process->vm_manager.MapMemoryBlock(target_address, buffer, 0, buffer->size(), | ||||||
|  |                                                          MemoryState::Private); | ||||||
|  |         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||||
|  | 
 | ||||||
|  |         const u32_le input[]{ | ||||||
|  |             IPC::MakeHeader(0, 0, 2), IPC::StaticBufferDesc(buffer->size(), 0), target_address, | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||||
|  | 
 | ||||||
|  |         CHECK(context.GetStaticBuffer(0) == *buffer); | ||||||
|  | 
 | ||||||
|  |         REQUIRE(process->vm_manager.UnmapRange(target_address, buffer->size()) == RESULT_SUCCESS); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     SECTION("translates mixed params") { |     SECTION("translates mixed params") { | ||||||
|  |         auto buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||||
|  |         std::fill(buffer->begin(), buffer->end(), 0xCE); | ||||||
|  | 
 | ||||||
|  |         VAddr target_address = 0x10000000; | ||||||
|  |         auto result = process->vm_manager.MapMemoryBlock(target_address, buffer, 0, buffer->size(), | ||||||
|  |                                                          MemoryState::Private); | ||||||
|  |         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||||
|  | 
 | ||||||
|         auto a = MakeObject(); |         auto a = MakeObject(); | ||||||
|         const u32_le input[]{ |         const u32_le input[]{ | ||||||
|             IPC::MakeHeader(0, 2, 4), |             IPC::MakeHeader(0, 2, 6), | ||||||
|             0x12345678, |             0x12345678, | ||||||
|             0xABCDEF00, |             0xABCDEF00, | ||||||
|             IPC::MoveHandleDesc(1), |             IPC::MoveHandleDesc(1), | ||||||
|             handle_table.Create(a).Unwrap(), |             handle_table.Create(a).Unwrap(), | ||||||
|             IPC::CallingPidDesc(), |             IPC::CallingPidDesc(), | ||||||
|             0, |             0, | ||||||
|  |             IPC::StaticBufferDesc(buffer->size(), 0), | ||||||
|  |             target_address, | ||||||
|         }; |         }; | ||||||
| 
 | 
 | ||||||
|         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); |         context.PopulateFromIncomingCommandBuffer(input, *process, handle_table); | ||||||
| 
 | 
 | ||||||
|         auto* output = context.CommandBuffer(); |         auto* output = context.CommandBuffer(); | ||||||
|         REQUIRE(output[1] == 0x12345678); |         CHECK(output[1] == 0x12345678); | ||||||
|         REQUIRE(output[2] == 0xABCDEF00); |         CHECK(output[2] == 0xABCDEF00); | ||||||
|         REQUIRE(context.GetIncomingHandle(output[4]) == a); |         CHECK(context.GetIncomingHandle(output[4]) == a); | ||||||
|         REQUIRE(output[6] == process->process_id); |         CHECK(output[6] == process->process_id); | ||||||
|  |         CHECK(context.GetStaticBuffer(0) == *buffer); | ||||||
|  | 
 | ||||||
|  |         REQUIRE(process->vm_manager.UnmapRange(target_address, buffer->size()) == RESULT_SUCCESS); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -211,6 +244,37 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") { | ||||||
|         REQUIRE(handle_table.GetGeneric(output[3]) == b); |         REQUIRE(handle_table.GetGeneric(output[3]) == b); | ||||||
|         REQUIRE(handle_table.GetGeneric(output[5]) == c); |         REQUIRE(handle_table.GetGeneric(output[5]) == c); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     SECTION("translates StaticBuffer descriptors") { | ||||||
|  |         std::vector<u8> input_buffer(Memory::PAGE_SIZE); | ||||||
|  |         std::fill(input_buffer.begin(), input_buffer.end(), 0xAB); | ||||||
|  | 
 | ||||||
|  |         context.AddStaticBuffer(0, input_buffer); | ||||||
|  | 
 | ||||||
|  |         auto output_buffer = std::make_shared<std::vector<u8>>(Memory::PAGE_SIZE); | ||||||
|  |         VAddr target_address = 0x10000000; | ||||||
|  |         auto result = process->vm_manager.MapMemoryBlock( | ||||||
|  |             target_address, output_buffer, 0, output_buffer->size(), MemoryState::Private); | ||||||
|  |         REQUIRE(result.Code() == RESULT_SUCCESS); | ||||||
|  | 
 | ||||||
|  |         input[0] = IPC::MakeHeader(0, 0, 2); | ||||||
|  |         input[1] = IPC::StaticBufferDesc(input_buffer.size(), 0); | ||||||
|  |         input[2] = target_address; | ||||||
|  | 
 | ||||||
|  |         // An entire command buffer plus enough space for one static buffer descriptor and its
 | ||||||
|  |         // target address
 | ||||||
|  |         std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2> output_cmdbuff; | ||||||
|  |         // Set up the output StaticBuffer
 | ||||||
|  |         output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH] = | ||||||
|  |             IPC::StaticBufferDesc(output_buffer->size(), 0); | ||||||
|  |         output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH + 1] = target_address; | ||||||
|  | 
 | ||||||
|  |         context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process, handle_table); | ||||||
|  | 
 | ||||||
|  |         CHECK(*output_buffer == input_buffer); | ||||||
|  |         REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) == | ||||||
|  |                 RESULT_SUCCESS); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace Kernel
 | } // namespace Kernel
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue