sm: Add sm:dmnt query extension
This commit is contained in:
33
stratosphere/sm/source/sm_dmnt_service.cpp
Normal file
33
stratosphere/sm/source/sm_dmnt_service.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#include "sm_dmnt_service.hpp"
|
||||
#include "sm_registration.hpp"
|
||||
|
||||
Result DmntService::AtmosphereGetRecord(Out<SmServiceRecord> record, SmServiceName service) {
|
||||
return Registration::GetServiceRecord(smEncodeName(service.name), record.GetPointer());
|
||||
}
|
||||
|
||||
void DmntService::AtmosphereListRecords(OutBuffer<SmServiceRecord> records, Out<u64> out_count, u64 offset) {
|
||||
Registration::ListServiceRecords(offset, records.num_elements, records.buffer, out_count.GetPointer());
|
||||
}
|
||||
|
||||
void DmntService::AtmosphereGetRecordSize(Out<u64> record_size) {
|
||||
record_size.SetValue(sizeof(SmServiceRecord));
|
||||
}
|
||||
|
||||
40
stratosphere/sm/source/sm_dmnt_service.hpp
Normal file
40
stratosphere/sm/source/sm_dmnt_service.hpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
#include <stratosphere.hpp>
|
||||
#include "sm_types.hpp"
|
||||
|
||||
enum DmntServiceCmd {
|
||||
Dmnt_Cmd_AtmosphereGetRecord = 65000,
|
||||
Dmnt_Cmd_AtmosphereListRecords = 65001,
|
||||
Dmnt_Cmd_AtmosphereGetRecordSize = 65002,
|
||||
};
|
||||
|
||||
class DmntService final : public IServiceObject {
|
||||
private:
|
||||
/* Actual commands. */
|
||||
virtual Result AtmosphereGetRecord(Out<SmServiceRecord> record, SmServiceName service);
|
||||
virtual void AtmosphereListRecords(OutBuffer<SmServiceRecord> records, Out<u64> out_count, u64 offset);
|
||||
virtual void AtmosphereGetRecordSize(Out<u64> record_size);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetRecord, &DmntService::AtmosphereGetRecord>(),
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereListRecords, &DmntService::AtmosphereListRecords>(),
|
||||
MakeServiceCommandMeta<Dmnt_Cmd_AtmosphereGetRecordSize, &DmntService::AtmosphereGetRecordSize>(),
|
||||
};
|
||||
};
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "sm_manager_service.hpp"
|
||||
#include "sm_user_service.hpp"
|
||||
#include "sm_dmnt_service.hpp"
|
||||
#include "sm_registration.hpp"
|
||||
|
||||
extern "C" {
|
||||
@@ -82,6 +83,17 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
server_manager->AddWaitable(new ExistingPortServer<ManagerService>(smm_h, 1));
|
||||
|
||||
/*===== ATMOSPHERE EXTENSION =====*/
|
||||
/* Create sm:dmnt manually. */
|
||||
Handle smdmnt_h;
|
||||
if (R_FAILED(Registration::RegisterServiceForSelf(smEncodeName("sm:dmnt"), 1, false, &smdmnt_h))) {
|
||||
/* TODO: Panic. */
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
server_manager->AddWaitable(new ExistingPortServer<DmntService>(smm_h, 1));;
|
||||
/*================================*/
|
||||
|
||||
/* Loop forever, servicing our services. */
|
||||
server_manager->Process();
|
||||
|
||||
@@ -23,7 +23,6 @@ enum ManagerServiceCmd {
|
||||
Manager_Cmd_RegisterProcess = 0,
|
||||
Manager_Cmd_UnregisterProcess = 1,
|
||||
|
||||
|
||||
Manager_Cmd_AtmosphereEndInitDefers = 65000,
|
||||
Manager_Cmd_AtmosphereHasMitm = 65001,
|
||||
};
|
||||
|
||||
@@ -562,3 +562,51 @@ Result Registration::AssociatePidTidForMitm(u64 pid, u64 tid) {
|
||||
}
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
void Registration::ConvertServiceToRecord(Registration::Service *service, SmServiceRecord *record) {
|
||||
record->service_name = service->service_name;
|
||||
record->owner_pid = service->owner_pid;
|
||||
record->max_sessions = service->max_sessions;
|
||||
record->mitm_pid = service->mitm_pid;
|
||||
record->mitm_waiting_ack_pid = service->mitm_waiting_ack_pid;
|
||||
record->is_light = service->is_light;
|
||||
record->mitm_waiting_ack = service->mitm_waiting_ack;
|
||||
}
|
||||
|
||||
Result Registration::GetServiceRecord(u64 service, SmServiceRecord *out) {
|
||||
if (!service) {
|
||||
return 0xC15;
|
||||
}
|
||||
|
||||
u64 service_name_len = GetServiceNameLength(service);
|
||||
|
||||
/* If the service has bytes after a null terminator, that's no good. */
|
||||
if (service_name_len != 8 && (service >> (8 * service_name_len))) {
|
||||
return 0xC15;
|
||||
}
|
||||
|
||||
Registration::Service *target_service = GetService(service);
|
||||
if (target_service == NULL) {
|
||||
return 0xE15;
|
||||
}
|
||||
|
||||
ConvertServiceToRecord(target_service, out);
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
void Registration::ListServiceRecords(u64 offset, u64 max_out, SmServiceRecord *out, u64 *out_count) {
|
||||
u64 count = 0;
|
||||
|
||||
for (auto it = g_service_list.begin(); it != g_service_list.end() && count < max_out; it++) {
|
||||
if (it->service_name != 0) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
} else {
|
||||
ConvertServiceToRecord(it, out++);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*out_count = count;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
#pragma once
|
||||
#include <switch.h>
|
||||
|
||||
#include "sm_types.hpp"
|
||||
|
||||
#define REGISTRATION_LIST_MAX_PROCESS (0x40)
|
||||
#define REGISTRATION_LIST_MAX_SERVICE (0x100)
|
||||
#define REGISTRATION_MAX_SAC_SIZE (0x200)
|
||||
@@ -81,4 +83,8 @@ class Registration {
|
||||
static Result UninstallMitmForPid(u64 pid, u64 service);
|
||||
static Result AcknowledgeMitmSessionForPid(u64 pid, u64 service, Handle *out, u64 *out_pid);
|
||||
static Result AssociatePidTidForMitm(u64 pid, u64 tid);
|
||||
|
||||
static void ConvertServiceToRecord(Registration::Service *service, SmServiceRecord *record);
|
||||
static Result GetServiceRecord(u64 service, SmServiceRecord *out);
|
||||
static void ListServiceRecords(u64 offset, u64 max_out, SmServiceRecord *out, u64 *out_count);
|
||||
};
|
||||
|
||||
@@ -19,4 +19,17 @@ struct SmServiceName {
|
||||
char name[sizeof(u64)];
|
||||
};
|
||||
|
||||
static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!");
|
||||
static_assert(__alignof__(SmServiceName) == 1, "SmServiceName definition!");
|
||||
|
||||
/* For Debug Monitor extensions. */
|
||||
struct SmServiceRecord {
|
||||
u64 service_name;
|
||||
u64 owner_pid;
|
||||
u64 max_sessions;
|
||||
u64 mitm_pid;
|
||||
u64 mitm_waiting_ack_pid;
|
||||
bool is_light;
|
||||
bool mitm_waiting_ack;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SmServiceRecord) == 0x30, "SmServiceRecord definition!");
|
||||
Reference in New Issue
Block a user