sm: Add sm:dmnt query extension

This commit is contained in:
Michael Scire
2019-01-20 15:59:09 -08:00
parent deb124138b
commit b6684ff845
8 changed files with 209 additions and 2 deletions

View 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));
}

View 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>(),
};
};

View File

@@ -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();

View File

@@ -23,7 +23,6 @@ enum ManagerServiceCmd {
Manager_Cmd_RegisterProcess = 0,
Manager_Cmd_UnregisterProcess = 1,
Manager_Cmd_AtmosphereEndInitDefers = 65000,
Manager_Cmd_AtmosphereHasMitm = 65001,
};

View File

@@ -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;
}

View File

@@ -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);
};

View File

@@ -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!");