mirror of
https://github.com/Takiiiiiiii/strato.git
synced 2025-07-17 08:46:39 +00:00
Milestone 3 - Services API
This commit adds the Services API and implements some services. It also changes the name of the application to Skyline and replaces the icon.
This commit is contained in:
148
app/src/main/cpp/skyline/kernel/ipc.cpp
Normal file
148
app/src/main/cpp/skyline/kernel/ipc.cpp
Normal file
@ -0,0 +1,148 @@
|
||||
#include <syslog.h>
|
||||
#include <cstdlib>
|
||||
#include "ipc.h"
|
||||
#include "types/KProcess.h"
|
||||
|
||||
namespace skyline::kernel::ipc {
|
||||
IpcRequest::IpcRequest(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state), tls() {
|
||||
u8 *currPtr = tls.data();
|
||||
state.thisProcess->ReadMemory(currPtr, state.thisThread->tls, constant::TlsIpcSize);
|
||||
|
||||
header = reinterpret_cast<CommandHeader *>(currPtr);
|
||||
currPtr += sizeof(CommandHeader);
|
||||
|
||||
if (header->handle_desc) {
|
||||
handleDesc = reinterpret_cast<HandleDescriptor *>(currPtr);
|
||||
currPtr += sizeof(HandleDescriptor) + (handleDesc->send_pid ? sizeof(u8) : 0);
|
||||
for (uint index = 0; handleDesc->copy_count > index; index++) {
|
||||
copyHandles.push_back(*reinterpret_cast<handle_t *>(currPtr));
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
for (uint index = 0; handleDesc->move_count > index; index++) {
|
||||
moveHandles.push_back(*reinterpret_cast<handle_t *>(currPtr));
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint index = 0; header->x_no > index; index++) {
|
||||
vecBufX.push_back(reinterpret_cast<BufferDescriptorX *>(currPtr));
|
||||
currPtr += sizeof(BufferDescriptorX);
|
||||
}
|
||||
|
||||
for (uint index = 0; header->a_no > index; index++) {
|
||||
vecBufA.push_back(reinterpret_cast<BufferDescriptorABW *>(currPtr));
|
||||
currPtr += sizeof(BufferDescriptorABW);
|
||||
}
|
||||
|
||||
for (uint index = 0; header->b_no > index; index++) {
|
||||
vecBufB.push_back(reinterpret_cast<BufferDescriptorABW *>(currPtr));
|
||||
currPtr += sizeof(BufferDescriptorABW);
|
||||
}
|
||||
|
||||
for (uint index = 0; header->w_no > index; index++) {
|
||||
vecBufW.push_back(reinterpret_cast<BufferDescriptorABW *>(currPtr));
|
||||
currPtr += sizeof(BufferDescriptorABW);
|
||||
}
|
||||
|
||||
currPtr = reinterpret_cast<u8 *>((((reinterpret_cast<u64>(currPtr) - reinterpret_cast<u64>(tls.data())) - 1U) & ~(constant::PaddingSum - 1U)) + constant::PaddingSum + reinterpret_cast<u64>(tls.data())); // Align to 16 bytes relative to start of TLS
|
||||
|
||||
if (isDomain) {
|
||||
domain = reinterpret_cast<DomainHeaderRequest *>(currPtr);
|
||||
currPtr += sizeof(DomainHeaderRequest);
|
||||
|
||||
payload = reinterpret_cast<PayloadHeader *>(currPtr);
|
||||
currPtr += sizeof(PayloadHeader);
|
||||
|
||||
cmdArg = currPtr;
|
||||
cmdArgSz = domain->payload_sz - sizeof(PayloadHeader);
|
||||
currPtr += domain->payload_sz;
|
||||
|
||||
for (uint index = 0; domain->input_count > index; index++) {
|
||||
domainObjects.push_back(*reinterpret_cast<handle_t *>(currPtr));
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
} else {
|
||||
payload = reinterpret_cast<PayloadHeader *>(currPtr);
|
||||
currPtr += sizeof(PayloadHeader);
|
||||
|
||||
cmdArg = currPtr;
|
||||
cmdArgSz = (header->raw_sz * sizeof(u32)) - (constant::PaddingSum + sizeof(PayloadHeader));
|
||||
currPtr += cmdArgSz;
|
||||
}
|
||||
|
||||
if (payload->magic != constant::SfciMagic)
|
||||
state.logger->Write(Logger::Warn, "Unexpected Magic in PayloadHeader: 0x{:X}", u32(payload->magic));
|
||||
|
||||
if (header->c_flag == static_cast<u8>(BufferCFlag::SingleDescriptor)) {
|
||||
vecBufC.push_back(reinterpret_cast<BufferDescriptorC *>(currPtr));
|
||||
} else if (header->c_flag > static_cast<u8>(BufferCFlag::SingleDescriptor)) {
|
||||
for (uint index = 0; (header->c_flag - 2) > index; index++) { // (c_flag - 2) C descriptors are present
|
||||
vecBufC.push_back(reinterpret_cast<BufferDescriptorC *>(currPtr));
|
||||
state.logger->Write(Logger::Debug, "Buf C #{} AD: 0x{:X} SZ: 0x{:X}", index, u64(vecBufC[index]->address), u16(vecBufC[index]->size));
|
||||
currPtr += sizeof(BufferDescriptorC);
|
||||
}
|
||||
}
|
||||
|
||||
state.logger->Write(Logger::Debug, "Header: X No: {}, A No: {}, B No: {}, W No: {}, C No: {}, Raw Size: {}", u8(header->x_no), u8(header->a_no), u8(header->b_no), u8(header->w_no), u8(vecBufC.size()), u64(cmdArgSz));
|
||||
if (header->handle_desc)
|
||||
state.logger->Write(Logger::Debug, "Handle Descriptor: Send PID: {}, Copy Count: {}, Move Count: {}", bool(handleDesc->send_pid), u32(handleDesc->copy_count), u32(handleDesc->move_count));
|
||||
if (isDomain)
|
||||
state.logger->Write(Logger::Debug, "Domain Header: Command: {}, Input Object Count: {}, Object ID: 0x{:X}", domain->command, domain->input_count, domain->object_id);
|
||||
state.logger->Write(Logger::Debug, "Data Payload: Command ID: 0x{:X}", u32(payload->value));
|
||||
}
|
||||
|
||||
IpcResponse::IpcResponse(bool isDomain, const DeviceState &state) : isDomain(isDomain), state(state) {}
|
||||
|
||||
void IpcResponse::WriteTls() {
|
||||
std::array<u8, constant::TlsIpcSize> tls{};
|
||||
u8 *currPtr = tls.data();
|
||||
auto header = reinterpret_cast<CommandHeader *>(currPtr);
|
||||
header->raw_sz = static_cast<u32>((sizeof(PayloadHeader) + argVec.size() + constant::PaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo
|
||||
header->handle_desc = (!copyHandles.empty() || !moveHandles.empty());
|
||||
currPtr += sizeof(CommandHeader);
|
||||
|
||||
if (header->handle_desc) {
|
||||
auto handleDesc = reinterpret_cast<HandleDescriptor *>(currPtr);
|
||||
handleDesc->copy_count = static_cast<u8>(copyHandles.size());
|
||||
handleDesc->move_count = static_cast<u8>(moveHandles.size());
|
||||
currPtr += sizeof(HandleDescriptor);
|
||||
|
||||
for (unsigned int copyHandle : copyHandles) {
|
||||
*reinterpret_cast<handle_t *>(currPtr) = copyHandle;
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
|
||||
for (unsigned int moveHandle : moveHandles) {
|
||||
*reinterpret_cast<handle_t *>(currPtr) = moveHandle;
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
}
|
||||
|
||||
u64 padding = ((((reinterpret_cast<u64>(currPtr) - reinterpret_cast<u64>(tls.data())) - 1U) & ~(constant::PaddingSum - 1U)) + constant::PaddingSum + (reinterpret_cast<u64>(tls.data()) - reinterpret_cast<u64>(currPtr))); // Calculate the amount of padding at the front
|
||||
currPtr += padding;
|
||||
|
||||
if (isDomain) {
|
||||
auto domain = reinterpret_cast<DomainHeaderResponse *>(currPtr);
|
||||
domain->output_count = static_cast<u32>(domainObjects.size());
|
||||
currPtr += sizeof(DomainHeaderResponse);
|
||||
}
|
||||
|
||||
auto payload = reinterpret_cast<PayloadHeader *>(currPtr);
|
||||
payload->magic = constant::SfcoMagic;
|
||||
payload->version = 1;
|
||||
payload->value = errorCode;
|
||||
currPtr += sizeof(PayloadHeader);
|
||||
if (!argVec.empty())
|
||||
memcpy(currPtr, argVec.data(), argVec.size());
|
||||
currPtr += argVec.size();
|
||||
|
||||
if(isDomain) {
|
||||
for (auto& domainObject : domainObjects) {
|
||||
*reinterpret_cast<handle_t *>(currPtr) = domainObject;
|
||||
currPtr += sizeof(handle_t);
|
||||
}
|
||||
}
|
||||
|
||||
state.thisProcess->WriteMemory(tls.data(), state.thisThread->tls, constant::TlsIpcSize);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user