Add String Support to IPC Push/Pop

This commit does some minor renaming/reordering in IPC and adds support for strings to IPC Push/Pop. It also fixes a tiny regression with the frametime display.
This commit is contained in:
◱ PixelyIon 2020-04-23 22:09:40 +05:30 committed by ◱ PixelyIon
parent 63154d05d1
commit 925d05d049
5 changed files with 39 additions and 19 deletions

View File

@ -62,7 +62,7 @@ namespace skyline::gpu {
if (frameTimestamp) { if (frameTimestamp) {
auto now = util::GetTimeNs(); auto now = util::GetTimeNs();
frametime = static_cast<u32>((now - frameTimestamp) / (constant::NsInSecond / 100)); // frametime / 100 is the real ms value, this is to retain the first two decimals frametime = static_cast<u32>((now - frameTimestamp) / 10000); // frametime / 100 is the real ms value, this is to retain the first two decimals
fps = static_cast<u16>(constant::NsInSecond / (now - frameTimestamp)); fps = static_cast<u16>(constant::NsInSecond / (now - frameTimestamp));
frameTimestamp = now; frameTimestamp = now;

View File

@ -143,7 +143,7 @@ namespace skyline::kernel::ipc {
memset(tls, 0, constant::TlsIpcSize); memset(tls, 0, constant::TlsIpcSize);
auto header = reinterpret_cast<CommandHeader *>(pointer); auto header = reinterpret_cast<CommandHeader *>(pointer);
header->rawSize = static_cast<u32>((sizeof(PayloadHeader) + argVec.size() + (domainObjects.size() * sizeof(KHandle)) + constant::IpcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo header->rawSize = static_cast<u32>((sizeof(PayloadHeader) + payload.size() + (domainObjects.size() * sizeof(KHandle)) + constant::IpcPaddingSum + (isDomain ? sizeof(DomainHeaderRequest) : 0)) / sizeof(u32)); // Size is in 32-bit units because Nintendo
header->handleDesc = (!copyHandles.empty() || !moveHandles.empty()); header->handleDesc = (!copyHandles.empty() || !moveHandles.empty());
pointer += sizeof(CommandHeader); pointer += sizeof(CommandHeader);
@ -174,15 +174,15 @@ namespace skyline::kernel::ipc {
pointer += sizeof(DomainHeaderResponse); pointer += sizeof(DomainHeaderResponse);
} }
auto payload = reinterpret_cast<PayloadHeader *>(pointer); auto payloadHeader = reinterpret_cast<PayloadHeader *>(pointer);
payload->magic = util::MakeMagic<u32>("SFCO"); // SFCO is the magic in IPC responses payloadHeader->magic = util::MakeMagic<u32>("SFCO"); // SFCO is the magic in IPC responses
payload->version = 1; payloadHeader->version = 1;
payload->value = errorCode; payloadHeader->value = errorCode;
pointer += sizeof(PayloadHeader); pointer += sizeof(PayloadHeader);
if (!argVec.empty()) if (!payload.empty())
std::memcpy(pointer, argVec.data(), argVec.size()); std::memcpy(pointer, payload.data(), payload.size());
pointer += argVec.size(); pointer += payload.size();
if (isDomain) { if (isDomain) {
for (auto &domainObject : domainObjects) { for (auto &domainObject : domainObjects) {
@ -191,6 +191,6 @@ namespace skyline::kernel::ipc {
} }
} }
state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->rawSize), u32(payload->value), copyHandles.size(), moveHandles.size()); state.logger->Debug("Output: Raw Size: {}, Command ID: 0x{:X}, Copy Handles: {}, Move Handles: {}", u32(header->rawSize), u32(payloadHeader->value), copyHandles.size(), moveHandles.size());
} }
} }

View File

@ -281,6 +281,16 @@ namespace skyline {
return value; return value;
} }
/**
* @brief This returns a std::string_view from the payload
* @param size The length of the string (0 means the string is null terminated)
*/
inline std::string_view PopString(size_t size = 0) {
auto view = size ? std::string_view(reinterpret_cast<const char*>(payloadOffset), size) : std::string_view(reinterpret_cast<const char*>(payloadOffset));
payloadOffset += view.length();
return view;
}
/** /**
* @brief This skips an object to pop off the top * @brief This skips an object to pop off the top
* @tparam ValueType The type of the object to skip * @tparam ValueType The type of the object to skip
@ -296,8 +306,8 @@ namespace skyline {
*/ */
class IpcResponse { class IpcResponse {
private: private:
std::vector<u8> argVec; //!< This holds all of the contents to be pushed to the payload
const DeviceState &state; //!< The state of the device const DeviceState &state; //!< The state of the device
std::vector<u8> payload; //!< This holds all of the contents to be pushed to the payload
public: public:
bool nWrite{}; //!< This is to signal the IPC handler to not write this, as it will be manually written bool nWrite{}; //!< This is to signal the IPC handler to not write this, as it will be manually written
@ -320,12 +330,22 @@ namespace skyline {
*/ */
template<typename ValueType> template<typename ValueType>
inline void Push(const ValueType &value) { inline void Push(const ValueType &value) {
argVec.reserve(argVec.size() + sizeof(ValueType)); auto size = payload.size();
auto item = reinterpret_cast<const u8 *>(&value); payload.resize(size + sizeof(ValueType));
for (uint index = 0; sizeof(ValueType) > index; index++) {
argVec.push_back(*item); std::memcpy(payload.data() + size, reinterpret_cast<const u8 *>(&value), sizeof(ValueType));
item++; }
}
/**
* @brief Writes a string to the payload
* @param string The string to write to the payload
*/
template<>
inline void Push(const std::string &string) {
auto size = payload.size();
payload.resize(size + string.size());
std::memcpy(payload.data() + size, string.data(), string.size());
} }
/** /**

View File

@ -12,7 +12,7 @@ namespace skyline::service::sm {
void IUserInterface::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {} void IUserInterface::Initialize(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {}
void IUserInterface::GetService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { void IUserInterface::GetService(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
std::string serviceName(reinterpret_cast<char *>(request.cmdArg)); std::string serviceName(request.PopString());
if (serviceName.empty()) { if (serviceName.empty()) {
response.errorCode = constant::status::ServiceInvName; response.errorCode = constant::status::ServiceInvName;

View File

@ -41,7 +41,7 @@ namespace skyline::service::visrv {
} }
void IApplicationDisplayService::OpenDisplay(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) { void IApplicationDisplayService::OpenDisplay(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
std::string displayName(reinterpret_cast<char *>(request.cmdArg)); std::string displayName(request.PopString());
state.logger->Debug("Setting display as: {}", displayName); state.logger->Debug("Setting display as: {}", displayName);
state.os->serviceManager.GetService<hosbinder::IHOSBinderDriver>(Service::hosbinder_IHOSBinderDriver)->SetDisplay(displayName); state.os->serviceManager.GetService<hosbinder::IHOSBinderDriver>(Service::hosbinder_IHOSBinderDriver)->SetDisplay(displayName);