mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
fs.mitm: Add domain support (closes #202)
This commit is contained in:
parent
9ae62a27dd
commit
f603dbfc98
6 changed files with 66 additions and 178 deletions
|
@ -17,47 +17,6 @@
|
|||
#include <switch.h>
|
||||
#include "fs_shim.h"
|
||||
|
||||
/* Necessary evil. */
|
||||
Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out) {
|
||||
u32* buf = (u32*)armGetTls();
|
||||
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
u32 object_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
buf[0] = IpcCommandType_Control;
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 1;
|
||||
raw->object_id = object_id;
|
||||
|
||||
Result rc = ipcDispatch(session);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct ipcCopyFromDomainResponse {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *raw = (struct ipcCopyFromDomainResponse*)r.Raw;
|
||||
|
||||
rc = raw->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
serviceCreate(out, r.Handles[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/* Missing fsp-srv commands. */
|
||||
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
|
||||
IpcCommand c;
|
||||
|
@ -68,7 +27,7 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
|
|||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 200;
|
||||
|
@ -77,60 +36,25 @@ Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out) {
|
|||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp = r.Raw;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(s, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
serviceCreate(&out->s, r.Handles[0]);
|
||||
serviceCreateSubservice(&out->s, s, &r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id);
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 200;
|
||||
|
||||
Result rc = serviceIpcDispatch(s);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParseForDomain(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 object_id;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*out_object_id = resp->object_id;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) {
|
||||
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
|
@ -141,7 +65,7 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
|
|||
u64 data_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(s, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 202;
|
||||
|
@ -152,58 +76,18 @@ Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id
|
|||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *resp = r.Raw;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(s, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
serviceCreate(&out->s, r.Handles[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id) {
|
||||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 cmd_id;
|
||||
FsStorageId storage_id;
|
||||
u64 data_id;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeaderForDomain(&c, sizeof(*raw), s->object_id);
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 202;
|
||||
raw->storage_id = storage_id;
|
||||
raw->data_id = data_id;
|
||||
|
||||
Result rc = serviceIpcDispatch(s);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParseForDomain(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
u32 object_id;
|
||||
} *resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
*out_object_id = resp->object_id;
|
||||
serviceCreateSubservice(&out->s, s, &r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,7 +107,7 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o
|
|||
u64 len;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(&f->s, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 5;
|
||||
|
@ -235,13 +119,14 @@ Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *o
|
|||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
FsRangeInfo range_info;
|
||||
} *resp = r.Raw;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&f->s, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
|
||||
|
@ -263,7 +148,7 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI
|
|||
u64 len;
|
||||
} *raw;
|
||||
|
||||
raw = ipcPrepareHeader(&c, sizeof(*raw));
|
||||
raw = serviceIpcPrepareHeader(&s->s, &c, sizeof(*raw));
|
||||
|
||||
raw->magic = SFCI_MAGIC;
|
||||
raw->cmd_id = 5;
|
||||
|
@ -275,13 +160,14 @@ Result fsStorageOperateRange(FsStorage* s, u32 op_id, u64 off, u64 len, FsRangeI
|
|||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
IpcParsedCommand r;
|
||||
ipcParse(&r);
|
||||
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
FsRangeInfo range_info;
|
||||
} *resp = r.Raw;
|
||||
} *resp;
|
||||
|
||||
serviceIpcParse(&s->s, &r, sizeof(*resp));
|
||||
resp = r.Raw;
|
||||
|
||||
rc = resp->result;
|
||||
if (R_SUCCEEDED(rc) && out) *out = resp->range_info;
|
||||
|
|
|
@ -16,14 +16,9 @@ typedef struct {
|
|||
u32 flags[0x40/sizeof(u32)];
|
||||
} FsRangeInfo;
|
||||
|
||||
/* Necessary evils. */
|
||||
Result ipcCopyFromDomain(Handle session, u32 object_id, Service *out);
|
||||
|
||||
/* Missing fsp-srv commands. */
|
||||
Result fsOpenDataStorageByCurrentProcessFwd(Service* s, FsStorage* out);
|
||||
Result fsOpenDataStorageByCurrentProcessFromDomainFwd(Service* s, u32 *out_object_id);
|
||||
Result fsOpenDataStorageByDataId(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
|
||||
Result fsOpenDataStorageByDataIdFromDomain(Service* s, FsStorageId storage_id, u64 data_id, u32 *out_object_id);
|
||||
Result fsOpenDataStorageByDataIdFwd(Service* s, FsStorageId storage_id, u64 data_id, FsStorage* out);
|
||||
|
||||
/* Missing FS File commands. */
|
||||
Result fsFileOperateRange(FsFile* f, u32 op_id, u64 off, u64 len, FsRangeInfo *out);
|
||||
|
|
|
@ -91,7 +91,11 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
|
|||
Result rc;
|
||||
if (this->romfs_storage != nullptr) {
|
||||
if (this->get_owner() != NULL) {
|
||||
rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id);
|
||||
FsStorage s = {0};
|
||||
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &s);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
out_domain_id = s.s.object_id;
|
||||
}
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
@ -102,15 +106,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
|
|||
} else {
|
||||
FsStorage data_storage;
|
||||
FsFile data_file;
|
||||
|
||||
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage);
|
||||
|
||||
if (this->get_owner() == NULL) {
|
||||
rc = fsOpenDataStorageByCurrentProcessFwd(this->forward_service, &data_storage);
|
||||
} else {
|
||||
rc = fsOpenDataStorageByCurrentProcessFromDomainFwd(this->forward_service, &out_domain_id);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s);
|
||||
}
|
||||
}
|
||||
Log(armGetTls(), 0x100);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
|
||||
|
@ -123,6 +121,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
|
|||
out_session = new IPCSession<IStorageInterface>(out_storage);
|
||||
if (this->get_owner() == NULL) {
|
||||
FsMitMWorker::AddWaitable(out_session);
|
||||
} else {
|
||||
out_domain_id = data_storage.s.object_id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,14 +140,9 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
|
|||
FsFile data_file;
|
||||
u32 out_domain_id = 0;
|
||||
Result rc;
|
||||
if (this->get_owner() == NULL) {
|
||||
rc = fsOpenDataStorageByDataId(this->forward_service, storage_id, data_id, &data_storage);
|
||||
} else {
|
||||
rc = fsOpenDataStorageByDataIdFromDomain(this->forward_service, storage_id, data_id, &out_domain_id);
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
rc = ipcCopyFromDomain(this->forward_service->handle, out_domain_id, &data_storage.s);
|
||||
}
|
||||
}
|
||||
|
||||
rc = fsOpenDataStorageByDataIdFwd(this->forward_service, storage_id, data_id, &data_storage);
|
||||
|
||||
if (R_SUCCEEDED(rc)) {
|
||||
/* TODO: Is there a sensible path that ends in ".romfs" we can use?" */
|
||||
if (R_SUCCEEDED(Utils::OpenSdFileForAtmosphere(data_id, "romfs.bin", FS_OPEN_READ, &data_file))) {
|
||||
|
@ -157,6 +152,8 @@ std::tuple<Result, OutSession<IStorageInterface>> FsMitMService::open_data_stora
|
|||
}
|
||||
if (this->get_owner() == NULL) {
|
||||
FsMitMWorker::AddWaitable(out_session);
|
||||
} else {
|
||||
out_domain_id = data_storage.s.object_id;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,20 +87,20 @@ class MitMSession final : public ISession<T> {
|
|||
|
||||
if (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext) {
|
||||
std::shared_ptr<IServiceObject> obj;
|
||||
if (r.IsDomainMessage) {
|
||||
obj = this->domain->get_domain_object(r.ThisObjectId);
|
||||
if (obj != nullptr && r.MessageType == DomainMessageType_Close) {
|
||||
if (r.ThisObjectId == this->mitm_domain_id) {
|
||||
if (r.IsDomainRequest) {
|
||||
obj = this->domain->get_domain_object(r.InThisObjectId);
|
||||
if (obj != nullptr && r.InMessageType == DomainMessageType_Close) {
|
||||
if (r.InThisObjectId == this->mitm_domain_id) {
|
||||
Reboot();
|
||||
}
|
||||
this->domain->delete_object(r.ThisObjectId);
|
||||
this->domain->delete_object(r.InThisObjectId);
|
||||
struct {
|
||||
u64 magic;
|
||||
u64 result;
|
||||
} *o_resp;
|
||||
|
||||
o_resp = (decltype(o_resp)) ipcPrepareHeaderForDomain(&c, sizeof(*o_resp), 0);
|
||||
*(DomainMessageHeader *)((uintptr_t)o_resp - sizeof(DomainMessageHeader)) = {0};
|
||||
*(DomainResponseHeader *)((uintptr_t)o_resp - sizeof(DomainResponseHeader)) = {0};
|
||||
o_resp->magic = SFCO_MAGIC;
|
||||
o_resp->result = 0x0;
|
||||
Log(armGetTls(), 0x100);
|
||||
|
@ -112,8 +112,9 @@ class MitMSession final : public ISession<T> {
|
|||
if (obj != nullptr) {
|
||||
retval = obj->dispatch(r, c, cmd_id, (u8 *)this->pointer_buffer.data(), this->pointer_buffer.size());
|
||||
if (R_SUCCEEDED(retval)) {
|
||||
if (r.IsDomainMessage) {
|
||||
ipcParseForDomain(&cur_out_r);
|
||||
if (r.IsDomainRequest) {
|
||||
/* We never work with out object ids, so this should be fine. */
|
||||
ipcParseDomainResponse(&cur_out_r, 0);
|
||||
} else {
|
||||
ipcParse(&cur_out_r);
|
||||
}
|
||||
|
@ -182,8 +183,9 @@ class MitMSession final : public ISession<T> {
|
|||
Log(armGetTls(), 0x100);
|
||||
retval = serviceIpcDispatch(&forward_service);
|
||||
if (R_SUCCEEDED(retval)) {
|
||||
if (r.IsDomainMessage) {
|
||||
ipcParseForDomain(&cur_out_r);
|
||||
if (r.IsDomainRequest) {
|
||||
/* We never work with out object ids, so this should be fine. */
|
||||
ipcParseDomainResponse(&cur_out_r, 0);
|
||||
} else {
|
||||
ipcParse(&cur_out_r);
|
||||
}
|
||||
|
|
|
@ -459,7 +459,9 @@ struct Encoder<std::tuple<Args...>> {
|
|||
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value - sizeof(Result));
|
||||
} else {
|
||||
raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(*raw) + size_in_raw_data_for_arguments<Args... >::value + (num_out_sessions_in_arguments<Args... >::value * sizeof(u32)) - sizeof(Result), 0);
|
||||
*((DomainMessageHeader *)((uintptr_t)raw - sizeof(DomainMessageHeader))) = {0};
|
||||
auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader));
|
||||
*resp_header = {0};
|
||||
resp_header->NumObjectIds = num_out_sessions_in_arguments<Args... >::value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -474,7 +476,13 @@ struct Encoder<std::tuple<Args...>> {
|
|||
if (R_FAILED(rc)) {
|
||||
std::fill(tls, tls + 0x100, 0x00);
|
||||
ipcInitialize(&out_command);
|
||||
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw));
|
||||
if (domain_owner != NULL) {
|
||||
raw = (decltype(raw))ipcPrepareHeaderForDomain(&out_command, sizeof(raw), 0);
|
||||
auto resp_header = (DomainResponseHeader *)((uintptr_t)raw - sizeof(DomainResponseHeader));
|
||||
*resp_header = {0};
|
||||
} else {
|
||||
raw = (decltype(raw))ipcPrepareHeader(&out_command, sizeof(raw));
|
||||
}
|
||||
raw->magic = SFCO_MAGIC;
|
||||
raw->result = rc;
|
||||
}
|
||||
|
@ -526,7 +534,7 @@ Result WrapIpcCommandImpl(Class *this_ptr, IpcParsedCommand& r, IpcCommand &out_
|
|||
auto args = Decoder<OutArgs, InArgsWithoutThis>::Decode(r, out_command, pointer_buffer);
|
||||
auto result = std::apply( [=](auto&&... args) { return (this_ptr->*IpcCommandImpl)(args...); }, args);
|
||||
DomainOwner *down = NULL;
|
||||
if (r.IsDomainMessage) {
|
||||
if (r.IsDomainRequest) {
|
||||
down = this_ptr->get_owner();
|
||||
}
|
||||
|
||||
|
|
|
@ -118,12 +118,12 @@ class ISession : public IWaitable {
|
|||
IpcCommand c;
|
||||
ipcInitialize(&c);
|
||||
|
||||
if (r.IsDomainMessage && this->active_object == NULL) {
|
||||
if (r.IsDomainRequest && this->active_object == NULL) {
|
||||
return 0xF601;
|
||||
}
|
||||
|
||||
|
||||
if (r.IsDomainMessage && r.MessageType == DomainMessageType_Close) {
|
||||
if (r.IsDomainRequest && r.InMessageType == DomainMessageType_Close) {
|
||||
this->domain->delete_object(this->active_object);
|
||||
this->active_object = NULL;
|
||||
struct {
|
||||
|
@ -198,11 +198,11 @@ class ISession : public IWaitable {
|
|||
Result retval = ipcParse(&r);
|
||||
if (R_SUCCEEDED(retval)) {
|
||||
if (this->is_domain && (r.CommandType == IpcCommandType_Request || r.CommandType == IpcCommandType_RequestWithContext)) {
|
||||
retval = ipcParseForDomain(&r);
|
||||
if (!r.IsDomainMessage || r.ThisObjectId >= DOMAIN_ID_MAX) {
|
||||
retval = ipcParseDomainRequest(&r);
|
||||
if (!r.IsDomainRequest || r.InThisObjectId >= DOMAIN_ID_MAX) {
|
||||
retval = 0xF601;
|
||||
} else {
|
||||
this->active_object = this->domain->get_domain_object(r.ThisObjectId);
|
||||
this->active_object = this->domain->get_domain_object(r.InThisObjectId);
|
||||
}
|
||||
} else {
|
||||
this->active_object = this->service_object;
|
||||
|
|
Loading…
Reference in a new issue