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:
		@@ -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
 | 
					inline const std::vector<u8>& RequestParser::PopStaticBuffer() {
 | 
				
			||||||
        // translation
 | 
					    const u32 sbuffer_descriptor = Pop<u32>();
 | 
				
			||||||
        Pop<VAddr>(); // Pop the calling process buffer address
 | 
					    // Pop the address from the incoming request buffer
 | 
				
			||||||
                      // and get the vaddr from the static buffers
 | 
					    Pop<VAddr>();
 | 
				
			||||||
        return cmdbuf[(0x100 >> 2) + bufferInfo.buffer_id * 2 + 1];
 | 
					
 | 
				
			||||||
    }
 | 
					    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
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user