mirror of
https://github.com/mikage-emu/mikage-dev.git
synced 2025-01-09 15:01:00 +01:00
122 lines
4.2 KiB
C++
122 lines
4.2 KiB
C++
#pragma once
|
|
|
|
#include "ipc.hpp"
|
|
|
|
#include <boost/hana/fwd/integral_constant.hpp>
|
|
|
|
#include <string>
|
|
|
|
namespace Platform {
|
|
|
|
/**
|
|
* ServiceManager: Manages "services" on the system. Services are nameless
|
|
* ports, which implies that applications can not connect to them through
|
|
* ConnectToPort system call, but instead always have to go through the "srv:"
|
|
* port.
|
|
*
|
|
* This system allows for fine-grained service access control for each process.
|
|
* Before connecting to services through the "srv:" port, applications must be
|
|
* registered to the SM module through the "srv:pm" service. An exception to
|
|
* this rule is made for processes that are embedded in the system firmware:
|
|
* Those processes generally may access any service withour prior registering
|
|
* (hence in particular solving the "hen or egg" problem due to which
|
|
* unregistered processes technically cannot access the srv:pm service to
|
|
* register themselves).
|
|
*/
|
|
namespace SM {
|
|
|
|
struct PortName {
|
|
PortName(const char* name) {
|
|
std::string strname(name);
|
|
length = strname.length();
|
|
uint32_t value = 0;
|
|
for (int i = 0; i < 8; ++i) {
|
|
char c = (i < length) ? strname[i] : 0;
|
|
value = (c << 24) | (value >> 8);
|
|
if (i == 3 || i == 7) {
|
|
this->name[i / 4] = value;
|
|
value = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
PortName(uint32_t low, uint32_t high, uint32_t length) : name{low, high}, length(length) {
|
|
}
|
|
|
|
static auto IPCDeserialize(uint32_t word_low, uint32_t word_high, uint32_t length) {
|
|
return PortName(word_low, word_high, length);
|
|
}
|
|
static auto IPCSerialize(const PortName& data) {
|
|
return std::make_tuple(data.name[0], data.name[1], data.length);
|
|
}
|
|
|
|
std::string ToString() const {
|
|
std::string ret;
|
|
for (unsigned index = 0; index < 8; ++index) {
|
|
auto word_index = index / 4;
|
|
auto byte_within_word = index % 4;
|
|
auto byte = static_cast<uint8_t>(name[word_index] >> (byte_within_word * 8));
|
|
if (byte == 0)
|
|
break;
|
|
ret += byte;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
using ipc_data_size = boost::hana::size_t<3>;
|
|
|
|
uint32_t name[2];
|
|
uint32_t length;
|
|
};
|
|
|
|
namespace SRV {
|
|
|
|
namespace IPC = Platform::IPC;
|
|
|
|
struct RegisterClient : IPC::IPCCommand<0x1>::add_process_id
|
|
::response {};
|
|
struct EnableNotification : IPC::IPCCommand<0x2>
|
|
::response::add_handle<IPC::HandleType::Semaphore> {};
|
|
struct RegisterService : IPC::IPCCommand<0x3>::add_serialized<PortName>::add_uint32
|
|
::response::add_and_close_handle<IPC::HandleType::ServerPort> {};
|
|
|
|
/**
|
|
* NOTE: The native SM module returns IPC header 0x00050042 if the service is
|
|
* not in the source application's extended header (as provided to
|
|
* srvpm:RegisterProcess), which makes our kernel implementation throw
|
|
* an error due to attempting to translate a null handle.
|
|
* TODO: Double-check whether the reference implementation special-cases
|
|
* null handles for this or not.
|
|
*/
|
|
struct GetServiceHandle : IPC::IPCCommand<0x5>::add_serialized<PortName>::add_uint32
|
|
::response::add_and_close_handle<IPC::HandleType::ClientSession> {};
|
|
struct Subscribe : IPC::IPCCommand<0x9>::add_uint32
|
|
::response {};
|
|
|
|
struct PublishToSubscriber : IPC::IPCCommand<0xc>::add_uint32::add_uint32
|
|
::response {};
|
|
|
|
} // namespace SRV
|
|
|
|
namespace SRVPM {
|
|
|
|
// NOTE: This returns 0xe7e3ffff on success, and 0xd8606408 on error
|
|
struct PublishToAll : IPC::IPCCommand<0x402>::add_uint32
|
|
::response {};
|
|
|
|
/**
|
|
* Authorizes a process to access services listed in the static buffer
|
|
*
|
|
* Inputs:
|
|
* - ProcessId for the process to authorize
|
|
* - Number of words in the given static buffer (i.e. twice the number of services to grant access to)
|
|
* - List of PortNames of accessible services
|
|
*/
|
|
struct RegisterProcess : IPC::IPCCommand<0x403>::add_uint32::add_uint32::add_static_buffer
|
|
::response {};
|
|
|
|
} // namespace SRVPM
|
|
|
|
} // namespace SM
|
|
|
|
} // namespace Platform
|