skyline/app/src/main/cpp/skyline/services/serviceman.cpp
◱ PixelyIon c005d7df74 Framebuffer and NativeActivity
What was added:
* Framebuffer
* NativeActivity
* NV Services
* IOCTL Handler
* NV Devices:
* * /dev/nvmap - 0xC0080101, 0xC0080103, 0xC0200104, 0xC0180105, 0xC00C0109, 0xC008010E
* * /dev/nvhost-as-gpu
* * /dev/nvhost-channel - 0x40044801, 0xC0104809, 0xC010480B, 0xC018480C, 0x4004480D, 0xC020481A, 0x40084714
* * /dev/nvhost-ctrl
* * /dev/nvhost-ctrl-gpu - 0x80044701, 0x80284702, 0xC0184706, 0xC0B04705, 0x80084714
* SVCs:
* * SetMemoryAttribute
* * CreateTransferMemory
* * ResetSignal
* * GetSystemTick
* Addition of Compact Logger
What was fixed:
* SVCs:
* * SetHeapSize
* * SetMemoryAttribute
* * QueryMemory
* A release build would not set CMAKE_BUILD_TYPE to "RELEASE"
* The logger code was simplified
2019-11-15 19:30:04 +00:00

231 lines
11 KiB
C++

#include "serviceman.h"
#include <kernel/types/KProcess.h>
#include "sm/sm.h"
#include "set/sys.h"
#include "apm/apm.h"
#include "am/applet.h"
#include "am/appletController.h"
#include "fatal/fatal.h"
#include "hid/hid.h"
#include "time/timesrv.h"
#include "fs/fs.h"
#include "nvdrv/nvdrv.h"
#include "vi/vi_m.h"
#include "nvnflinger/dispdrv.h"
namespace skyline::kernel::service {
ServiceManager::ServiceManager(const DeviceState &state) : state(state) {}
std::shared_ptr<BaseService> ServiceManager::GetService(const Service serviceType) {
std::shared_ptr<BaseService> serviceObj;
switch (serviceType) {
case Service::sm:
serviceObj = std::make_shared<sm::sm>(state, *this);
break;
case Service::fatal_u:
serviceObj = std::make_shared<fatal::fatalU>(state, *this);
break;
case Service::set_sys:
serviceObj = std::make_shared<set::sys>(state, *this);
break;
case Service::apm:
serviceObj = std::make_shared<apm::apm>(state, *this);
break;
case Service::apm_ISession:
serviceObj = std::make_shared<apm::ISession>(state, *this);
break;
case Service::am_appletOE:
serviceObj = std::make_shared<am::appletOE>(state, *this);
break;
case Service::am_appletAE:
serviceObj = std::make_shared<am::appletAE>(state, *this);
break;
case Service::am_IApplicationProxy:
serviceObj = std::make_shared<am::IApplicationProxy>(state, *this);
break;
case Service::am_ILibraryAppletProxy:
serviceObj = std::make_shared<am::ILibraryAppletProxy>(state, *this);
break;
case Service::am_ICommonStateGetter:
serviceObj = std::make_shared<am::ICommonStateGetter>(state, *this);
break;
case Service::am_IWindowController:
serviceObj = std::make_shared<am::IWindowController>(state, *this);
break;
case Service::am_IAudioController:
serviceObj = std::make_shared<am::IAudioController>(state, *this);
break;
case Service::am_IDisplayController:
serviceObj = std::make_shared<am::IDisplayController>(state, *this);
break;
case Service::am_ISelfController:
serviceObj = std::make_shared<am::ISelfController>(state, *this);
break;
case Service::am_ILibraryAppletCreator:
serviceObj = std::make_shared<am::ILibraryAppletCreator>(state, *this);
break;
case Service::am_IApplicationFunctions:
serviceObj = std::make_shared<am::IApplicationFunctions>(state, *this);
break;
case Service::am_IDebugFunctions:
serviceObj = std::make_shared<am::IDebugFunctions>(state, *this);
break;
case Service::hid:
serviceObj = std::make_shared<hid::hid>(state, *this);
break;
case Service::hid_IAppletResource:
serviceObj = std::make_shared<hid::IAppletResource>(state, *this);
break;
case Service::time:
serviceObj = std::make_shared<time::time>(state, *this);
break;
case Service::fs_fsp:
serviceObj = std::make_shared<fs::fsp>(state, *this);
break;
case Service::nvdrv:
serviceObj = std::make_shared<nvdrv::nvdrv>(state, *this);
break;
case Service::vi_m:
serviceObj = std::make_shared<vi::vi_m>(state, *this);
break;
case Service::vi_IApplicationDisplayService:
serviceObj = std::make_shared<vi::IApplicationDisplayService>(state, *this);
break;
case Service::vi_ISystemDisplayService:
serviceObj = std::make_shared<vi::ISystemDisplayService>(state, *this);
break;
case Service::vi_IManagerDisplayService:
serviceObj = std::make_shared<vi::IManagerDisplayService>(state, *this);
break;
case Service::nvnflinger_dispdrv:
serviceObj = std::make_shared<nvnflinger::dispdrv>(state, *this);
break;
default:
throw exception("GetService called on missing object, type: {}", serviceType);
}
serviceVec.push_back(serviceObj);
return serviceObj;
}
handle_t ServiceManager::NewSession(const Service serviceType) {
return state.thisProcess->NewHandle<type::KSession>(GetService(serviceType)).handle;
}
std::shared_ptr<BaseService> ServiceManager::NewService(const std::string &serviceName, type::KSession &session, ipc::IpcResponse &response) {
auto serviceObject = GetService(ServiceString.at(serviceName));
handle_t handle{};
if (response.isDomain) {
session.domainTable[++session.handleIndex] = serviceObject;
response.domainObjects.push_back(session.handleIndex);
handle = session.handleIndex;
} else {
handle = state.thisProcess->NewHandle<type::KSession>(serviceObject).handle;
response.moveHandles.push_back(handle);
}
state.logger->Debug("Service has been created: \"{}\" (0x{:X})", serviceName, handle);
return serviceObject;
}
void ServiceManager::RegisterService(std::shared_ptr<BaseService> serviceObject, type::KSession &session, ipc::IpcResponse &response) { // NOLINT(performance-unnecessary-value-param)
serviceVec.push_back(serviceObject);
handle_t handle{};
if (response.isDomain) {
session.domainTable[session.handleIndex] = serviceObject;
response.domainObjects.push_back(session.handleIndex);
handle = session.handleIndex++;
} else {
handle = state.thisProcess->NewHandle<type::KSession>(serviceObject).handle;
response.moveHandles.push_back(handle);
}
state.logger->Debug("Service has been registered: \"{}\" (0x{:X})", serviceObject->getName(), handle);
}
void ServiceManager::CloseSession(const handle_t handle) {
auto session = state.thisProcess->GetHandle<type::KSession>(handle);
if (session->serviceStatus == type::KSession::ServiceStatus::Open) {
if (session->isDomain) {
for (const auto &[objectId, service] : session->domainTable)
serviceVec.erase(std::remove(serviceVec.begin(), serviceVec.end(), service), serviceVec.end());
} else
serviceVec.erase(std::remove(serviceVec.begin(), serviceVec.end(), session->serviceObject), serviceVec.end());
session->serviceStatus = type::KSession::ServiceStatus::Closed;
}
};
void ServiceManager::Loop() {
for (auto &service : serviceVec)
if (service->hasLoop)
service->Loop();
}
void ServiceManager::SyncRequestHandler(const handle_t handle) {
auto session = state.thisProcess->GetHandle<type::KSession>(handle);
state.logger->Debug("----Start----");
state.logger->Debug("Handle is 0x{:X}", handle);
if (session->serviceStatus == type::KSession::ServiceStatus::Open) {
ipc::IpcRequest request(session->isDomain, state);
ipc::IpcResponse response(session->isDomain, state);
switch (static_cast<ipc::CommandType>(request.header->type)) {
case ipc::CommandType::Request:
case ipc::CommandType::RequestWithContext:
if (session->isDomain) {
try {
auto service = session->domainTable.at(request.domain->object_id);
switch (static_cast<ipc::DomainCommand>(request.domain->command)) {
case ipc::DomainCommand::SendMessage:
service->HandleRequest(*session, request, response);
break;
case ipc::DomainCommand::CloseVHandle:
serviceVec.erase(std::remove(serviceVec.begin(), serviceVec.end(), service), serviceVec.end());
session->domainTable.erase(request.domain->object_id);
break;
}
} catch (std::out_of_range &) {
throw exception("Invalid object ID was used with domain request");
}
} else
session->serviceObject->HandleRequest(*session, request, response);
if (!response.nWrite)
response.WriteTls();
break;
case ipc::CommandType::Control:
case ipc::CommandType::ControlWithContext:
state.logger->Debug("Control IPC Message: {}", request.payload->value);
switch (static_cast<ipc::ControlCommand>(request.payload->value)) {
case ipc::ControlCommand::ConvertCurrentObjectToDomain:
response.WriteValue(session->ConvertDomain());
break;
case ipc::ControlCommand::CloneCurrentObject:
case ipc::ControlCommand::CloneCurrentObjectEx:
CloneSession(*session, request, response);
break;
case ipc::ControlCommand::QueryPointerBufferSize:
response.WriteValue<u32>(0x1000);
break;
default:
throw exception("Unknown Control Command: {}", request.payload->value);
}
response.WriteTls();
break;
case ipc::CommandType::Close:
state.logger->Debug("Closing Session");
CloseSession(handle);
break;
default:
throw exception("Unimplemented IPC message type: {}", u16(request.header->type));
}
} else
state.logger->Warn("svcSendSyncRequest called on closed handle: 0x{:X}", handle);
state.logger->Debug("====End====");
}
void ServiceManager::CloneSession(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {
//NewService(session.serviceType, session, response);
}
}