sf: Change interface definition methodology (#1074)

* sf: Begin experimenting with new interface declaration format

* sf: convert fs interfaces to new format

* sf: finish conversion of libstrat to new definitions

* sf: convert loader to new format

* sf: convert spl to new format

* sf: update ncm for new format

* sf: convert pm to new format

* sf: convert ro/sm to new format

* sf: update fatal for new format

* sf: support building dmnt under new scheme

* sf: update ams.mitm for new format

* sf: correct invocation def for pointer holder

* fs: correct 10.x+ user bindings for Get*SpaceSize
This commit is contained in:
SciresM
2020-07-07 17:07:23 -07:00
committed by GitHub
parent 94eb2195d3
commit 9fde97cfdd
190 changed files with 3220 additions and 3172 deletions

View File

@@ -37,7 +37,7 @@ namespace ams::mitm::bpc_ams {
{
Handle bpcams_h;
R_ABORT_UNLESS(svcManageNamedPort(&bpcams_h, AtmosphereServiceName.name, AtmosphereMaxSessions));
g_server_manager.RegisterServer<bpc::AtmosphereService>(bpcams_h);
g_server_manager.RegisterServer<bpc::impl::IAtmosphereInterface, bpc::AtmosphereService>(bpcams_h);
}
/* Loop forever, servicing our services. */

View File

@@ -18,20 +18,21 @@
namespace ams::mitm::bpc {
class AtmosphereService final : public sf::IServiceObject {
private:
enum class CommandId {
RebootToFatalError = 65000,
SetRebootPayload = 65001,
};
private:
namespace impl {
#define AMS_BPC_MITM_ATMOSPHERE_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 65000, void, RebootToFatalError, (const ams::FatalErrorContext &ctx)) \
AMS_SF_METHOD_INFO(C, H, 65001, void, SetRebootPayload, (const ams::sf::InBuffer &payload))
AMS_SF_DEFINE_INTERFACE(IAtmosphereInterface, AMS_BPC_MITM_ATMOSPHERE_INTERFACE_INTERFACE_INFO)
}
class AtmosphereService final {
public:
void RebootToFatalError(const ams::FatalErrorContext &ctx);
void SetRebootPayload(const ams::sf::InBuffer &payload);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(RebootToFatalError),
MAKE_SERVICE_COMMAND_META(SetRebootPayload),
};
};
static_assert(impl::IsIAtmosphereInterface<AtmosphereService>);
}

View File

@@ -18,12 +18,19 @@
namespace ams::mitm::bpc {
class BpcMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
ShutdownSystem = 0,
RebootSystem = 1,
};
namespace impl {
#define AMS_BPC_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, ShutdownSystem, ()) \
AMS_SF_METHOD_INFO(C, H, 1, Result, RebootSystem, ())
AMS_SF_DEFINE_MITM_INTERFACE(IBpcMitmInterface, AMS_BPC_MITM_INTERFACE_INFO)
}
class BpcMitmService : public sf::MitmServiceImplBase {
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* We will mitm:
@@ -36,16 +43,10 @@ namespace ams::mitm::bpc {
client_info.override_status.IsHbl();
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(BpcMitmService) { /* ... */ }
protected:
/* Overridden commands. */
Result ShutdownSystem();
Result RebootSystem();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ShutdownSystem),
MAKE_SERVICE_COMMAND_META(RebootSystem),
};
};
static_assert(impl::IsIBpcMitmInterface<BpcMitmService>);
}

View File

@@ -39,7 +39,7 @@ namespace ams::mitm::bpc {
/* Create bpc mitm. */
const sm::ServiceName service_name = (hos::GetVersion() >= hos::Version_2_0_0) ? MitmServiceName : DeprecatedMitmServiceName;
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<BpcMitmService>(service_name));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<impl::IBpcMitmInterface, BpcMitmService>(service_name)));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -35,9 +35,9 @@ namespace ams::mitm::fs {
os::Mutex g_data_storage_lock(false);
os::Mutex g_storage_cache_lock(false);
std::unordered_map<u64, std::weak_ptr<IStorageInterface>> g_storage_cache;
std::unordered_map<u64, std::weak_ptr<ams::fssrv::sf::IStorage>> g_storage_cache;
std::shared_ptr<IStorageInterface> GetStorageCacheEntry(ncm::ProgramId program_id) {
std::shared_ptr<ams::fssrv::sf::IStorage> GetStorageCacheEntry(ncm::ProgramId program_id) {
std::scoped_lock lk(g_storage_cache_lock);
auto it = g_storage_cache.find(static_cast<u64>(program_id));
@@ -48,7 +48,7 @@ namespace ams::mitm::fs {
return it->second.lock();
}
void SetStorageCacheEntry(ncm::ProgramId program_id, std::shared_ptr<IStorageInterface> *new_intf) {
void SetStorageCacheEntry(ncm::ProgramId program_id, std::shared_ptr<ams::fssrv::sf::IStorage> *new_intf) {
std::scoped_lock lk(g_storage_cache_lock);
auto it = g_storage_cache.find(static_cast<u64>(program_id));
@@ -69,7 +69,17 @@ namespace ams::mitm::fs {
return (tmp != 0);
}
Result OpenHblWebContentFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type) {
template<typename... Arguments>
constexpr ALWAYS_INLINE auto MakeSharedFileSystem(Arguments &&... args) {
return sf::MakeShared<ams::fssrv::sf::IFileSystem, ams::fssrv::impl::FileSystemInterfaceAdapter>(std::forward<Arguments>(args)...);
}
template<typename... Arguments>
constexpr ALWAYS_INLINE auto MakeSharedStorage(Arguments &&... args) {
return sf::MakeShared<ams::fssrv::sf::IStorage, ams::fssrv::impl::StorageInterfaceAdapter>(std::forward<Arguments>(args)...);
}
Result OpenHblWebContentFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type) {
/* Verify eligibility. */
bool is_hbl;
R_UNLESS(R_SUCCEEDED(pm::info::IsHblProgramId(&is_hbl, program_id)), sm::mitm::ResultShouldForwardToSession());
@@ -88,11 +98,11 @@ namespace ams::mitm::fs {
const sf::cmif::DomainObjectId target_object_id{serviceGetObjectId(&sd_fs.s)};
std::unique_ptr<fs::fsa::IFileSystem> sd_ifs = std::make_unique<fs::RemoteFileSystem>(sd_fs);
out.SetValue(std::make_shared<IFileSystemInterface>(std::make_shared<fs::ReadOnlyFileSystem>(std::make_unique<fssystem::SubDirectoryFileSystem>(std::move(sd_ifs), AtmosphereHblWebContentDir)), false), target_object_id);
out.SetValue(MakeSharedFileSystem(std::make_shared<fs::ReadOnlyFileSystem>(std::make_unique<fssystem::SubDirectoryFileSystem>(std::move(sd_ifs), AtmosphereHblWebContentDir)), false), target_object_id);
return ResultSuccess();
}
Result OpenProgramSpecificWebContentFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type, Service *fwd, const fssrv::sf::Path *path, bool with_id) {
Result OpenProgramSpecificWebContentFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type, Service *fwd, const fssrv::sf::Path *path, bool with_id) {
/* Directory must exist. */
{
FsDir d;
@@ -132,13 +142,13 @@ namespace ams::mitm::fs {
new_fs = std::make_shared<fs::ReadOnlyFileSystem>(std::move(subdir_fs));
}
out.SetValue(std::make_shared<IFileSystemInterface>(std::move(new_fs), false), target_object_id);
out.SetValue(MakeSharedFileSystem(std::move(new_fs), false), target_object_id);
}
return ResultSuccess();
}
Result OpenWebContentFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type, Service *fwd, const fssrv::sf::Path *path, bool with_id, bool try_program_specific) {
Result OpenWebContentFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> &out, ncm::ProgramId client_program_id, ncm::ProgramId program_id, FsFileSystemType filesystem_type, Service *fwd, const fssrv::sf::Path *path, bool with_id, bool try_program_specific) {
/* Check first that we're a web applet opening web content. */
R_UNLESS(ncm::IsWebAppletId(client_program_id), sm::mitm::ResultShouldForwardToSession());
R_UNLESS(filesystem_type == FsFileSystemType_ContentManual, sm::mitm::ResultShouldForwardToSession());
@@ -155,15 +165,15 @@ namespace ams::mitm::fs {
}
Result FsMitmService::OpenFileSystemWithPatch(sf::Out<std::shared_ptr<IFileSystemInterface>> out, ncm::ProgramId program_id, u32 _filesystem_type) {
Result FsMitmService::OpenFileSystemWithPatch(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 _filesystem_type) {
return OpenWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast<FsFileSystemType>(_filesystem_type), this->forward_service.get(), nullptr, false, this->client_info.override_status.IsProgramSpecific());
}
Result FsMitmService::OpenFileSystemWithId(sf::Out<std::shared_ptr<IFileSystemInterface>> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type) {
Result FsMitmService::OpenFileSystemWithId(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type) {
return OpenWebContentFileSystem(out, this->client_info.program_id, program_id, static_cast<FsFileSystemType>(_filesystem_type), this->forward_service.get(), std::addressof(path), true, this->client_info.override_status.IsProgramSpecific());
}
Result FsMitmService::OpenSdCardFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> out) {
Result FsMitmService::OpenSdCardFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out) {
/* We only care about redirecting this for NS/emummc. */
R_UNLESS(this->client_info.program_id == ncm::SystemProgramId::Ns, sm::mitm::ResultShouldForwardToSession());
R_UNLESS(emummc::IsActive(), sm::mitm::ResultShouldForwardToSession());
@@ -175,11 +185,11 @@ namespace ams::mitm::fs {
/* Return output filesystem. */
std::shared_ptr<fs::fsa::IFileSystem> redir_fs = std::make_shared<fssystem::DirectoryRedirectionFileSystem>(std::make_shared<RemoteFileSystem>(sd_fs), "/Nintendo", emummc::GetNintendoDirPath());
out.SetValue(std::make_shared<IFileSystemInterface>(std::move(redir_fs), false), target_object_id);
out.SetValue(MakeSharedFileSystem(std::move(redir_fs), false), target_object_id);
return ResultSuccess();
}
Result FsMitmService::OpenSaveDataFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> out, u8 _space_id, const fs::SaveDataAttribute &attribute) {
Result FsMitmService::OpenSaveDataFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, u8 _space_id, const fs::SaveDataAttribute &attribute) {
/* We only want to intercept saves for games, right now. */
const bool is_game_or_hbl = this->client_info.override_status.IsHbl() || ncm::IsApplicationId(this->client_info.program_id);
R_UNLESS(is_game_or_hbl, sm::mitm::ResultShouldForwardToSession());
@@ -240,11 +250,11 @@ namespace ams::mitm::fs {
}
/* Set output. */
out.SetValue(std::make_shared<IFileSystemInterface>(std::move(dirsave_ifs), false), target_object_id);
out.SetValue(MakeSharedFileSystem(std::move(dirsave_ifs), false), target_object_id);
return ResultSuccess();
}
Result FsMitmService::OpenBisStorage(sf::Out<std::shared_ptr<IStorageInterface>> out, u32 _bis_partition_id) {
Result FsMitmService::OpenBisStorage(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, u32 _bis_partition_id) {
const ::FsBisPartitionId bis_partition_id = static_cast<::FsBisPartitionId>(_bis_partition_id);
/* Try to open a storage for the partition. */
@@ -265,23 +275,23 @@ namespace ams::mitm::fs {
/* Set output storage. */
if (bis_partition_id == FsBisPartitionId_BootPartition1Root) {
out.SetValue(std::make_shared<IStorageInterface>(new Boot0Storage(bis_storage, this->client_info)), target_object_id);
out.SetValue(MakeSharedStorage(new Boot0Storage(bis_storage, this->client_info)), target_object_id);
} else if (bis_partition_id == FsBisPartitionId_CalibrationBinary) {
out.SetValue(std::make_shared<IStorageInterface>(new CalibrationBinaryStorage(bis_storage, this->client_info)), target_object_id);
out.SetValue(MakeSharedStorage(new CalibrationBinaryStorage(bis_storage, this->client_info)), target_object_id);
} else {
if (can_write_bis || can_write_bis_for_choi_support) {
/* We can write, so create a writable storage. */
out.SetValue(std::make_shared<IStorageInterface>(new RemoteStorage(bis_storage)), target_object_id);
out.SetValue(MakeSharedStorage(new RemoteStorage(bis_storage)), target_object_id);
} else {
/* We can only read, so create a readable storage. */
out.SetValue(std::make_shared<IStorageInterface>(new ReadOnlyStorageAdapter(new RemoteStorage(bis_storage))), target_object_id);
out.SetValue(MakeSharedStorage(new ReadOnlyStorageAdapter(new RemoteStorage(bis_storage))), target_object_id);
}
}
return ResultSuccess();
}
Result FsMitmService::OpenDataStorageByCurrentProcess(sf::Out<std::shared_ptr<IStorageInterface>> out) {
Result FsMitmService::OpenDataStorageByCurrentProcess(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out) {
/* Only mitm if we should override contents for the current process. */
R_UNLESS(this->client_info.override_status.IsProgramSpecific(), sm::mitm::ResultShouldForwardToSession());
@@ -298,7 +308,7 @@ namespace ams::mitm::fs {
/* Try to get a storage from the cache. */
{
std::shared_ptr<IStorageInterface> cached_storage = GetStorageCacheEntry(this->client_info.program_id);
std::shared_ptr<ams::fssrv::sf::IStorage> cached_storage = GetStorageCacheEntry(this->client_info.program_id);
if (cached_storage != nullptr) {
out.SetValue(std::move(cached_storage), target_object_id);
return ResultSuccess();
@@ -307,18 +317,18 @@ namespace ams::mitm::fs {
/* Make a new layered romfs, and cache to storage. */
{
std::shared_ptr<IStorageInterface> new_storage_intf = nullptr;
std::shared_ptr<ams::fssrv::sf::IStorage> new_storage_intf = nullptr;
/* Create the layered storage. */
FsFile data_file;
if (R_SUCCEEDED(OpenAtmosphereSdFile(&data_file, this->client_info.program_id, "romfs.bin", OpenMode_Read))) {
auto layered_storage = std::make_shared<LayeredRomfsStorage>(std::make_unique<ReadOnlyStorageAdapter>(new RemoteStorage(data_storage)), std::make_unique<ReadOnlyStorageAdapter>(new FileStorage(new RemoteFile(data_file))), this->client_info.program_id);
layered_storage->BeginInitialize();
new_storage_intf = std::make_shared<IStorageInterface>(layered_storage);
new_storage_intf = MakeSharedStorage(layered_storage);
} else {
auto layered_storage = std::make_shared<LayeredRomfsStorage>(std::make_unique<ReadOnlyStorageAdapter>(new RemoteStorage(data_storage)), nullptr, this->client_info.program_id);
layered_storage->BeginInitialize();
new_storage_intf = std::make_shared<IStorageInterface>(layered_storage);
new_storage_intf = MakeSharedStorage(layered_storage);
}
SetStorageCacheEntry(this->client_info.program_id, &new_storage_intf);
@@ -328,7 +338,7 @@ namespace ams::mitm::fs {
return ResultSuccess();
}
Result FsMitmService::OpenDataStorageByDataId(sf::Out<std::shared_ptr<IStorageInterface>> out, ncm::DataId _data_id, u8 storage_id) {
Result FsMitmService::OpenDataStorageByDataId(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, ncm::DataId _data_id, u8 storage_id) {
/* Only mitm if we should override contents for the current process. */
R_UNLESS(this->client_info.override_status.IsProgramSpecific(), sm::mitm::ResultShouldForwardToSession());
@@ -348,7 +358,7 @@ namespace ams::mitm::fs {
/* Try to get a storage from the cache. */
{
std::shared_ptr<IStorageInterface> cached_storage = GetStorageCacheEntry(data_id);
std::shared_ptr<ams::fssrv::sf::IStorage> cached_storage = GetStorageCacheEntry(data_id);
if (cached_storage != nullptr) {
out.SetValue(std::move(cached_storage), target_object_id);
return ResultSuccess();
@@ -357,18 +367,18 @@ namespace ams::mitm::fs {
/* Make a new layered romfs, and cache to storage. */
{
std::shared_ptr<IStorageInterface> new_storage_intf = nullptr;
std::shared_ptr<ams::fssrv::sf::IStorage> new_storage_intf = nullptr;
/* Create the layered storage. */
FsFile data_file;
if (R_SUCCEEDED(OpenAtmosphereSdFile(&data_file, data_id, "romfs.bin", OpenMode_Read))) {
auto layered_storage = std::make_shared<LayeredRomfsStorage>(std::make_unique<ReadOnlyStorageAdapter>(new RemoteStorage(data_storage)), std::make_unique<ReadOnlyStorageAdapter>(new FileStorage(new RemoteFile(data_file))), data_id);
layered_storage->BeginInitialize();
new_storage_intf = std::make_shared<IStorageInterface>(layered_storage);
new_storage_intf = MakeSharedStorage(layered_storage);
} else {
auto layered_storage = std::make_shared<LayeredRomfsStorage>(std::make_unique<ReadOnlyStorageAdapter>(new RemoteStorage(data_storage)), nullptr, data_id);
layered_storage->BeginInitialize();
new_storage_intf = std::make_shared<IStorageInterface>(layered_storage);
new_storage_intf = MakeSharedStorage(layered_storage);
}
SetStorageCacheEntry(data_id, &new_storage_intf);

View File

@@ -20,30 +20,26 @@
namespace ams::mitm::fs {
using IStorageInterface = ams::fssrv::impl::StorageInterfaceAdapter;
using IFileSystemInterface = ams::fssrv::impl::FileSystemInterfaceAdapter;
namespace {
/* TODO: Consider re-enabling the mitm flag logic. */
#define AMS_FS_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 7, Result, OpenFileSystemWithPatch, (sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 _filesystem_type), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, OpenFileSystemWithId, (sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 18, Result, OpenSdCardFileSystem, (sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out)) \
AMS_SF_METHOD_INFO(C, H, 51, Result, OpenSaveDataFileSystem, (sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, u8 space_id, const ams::fs::SaveDataAttribute &attribute)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, OpenBisStorage, (sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, u32 bis_partition_id)) \
AMS_SF_METHOD_INFO(C, H, 200, Result, OpenDataStorageByCurrentProcess, (sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out)) \
AMS_SF_METHOD_INFO(C, H, 202, Result, OpenDataStorageByDataId, (sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, ncm::DataId data_id, u8 storage_id))
class FsMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
OpenFileSystemDeprecated = 0,
AMS_SF_DEFINE_MITM_INTERFACE(IFsMitmInterface, AMS_FS_MITM_INTERFACE_INFO)
SetCurrentProcess = 1,
OpenFileSystemWithPatch = 7,
OpenFileSystemWithId = 8,
}
OpenSdCardFileSystem = 18,
OpenSaveDataFileSystem = 51,
OpenBisStorage = 12,
OpenDataStorageByCurrentProcess = 200,
OpenDataStorageByDataId = 202,
};
class FsMitmService : public sf::MitmServiceImplBase {
public:
NX_CONSTEXPR bool ShouldMitmProgramId(const ncm::ProgramId program_id) {
using MitmServiceImplBase::MitmServiceImplBase;
public:
static constexpr ALWAYS_INLINE bool ShouldMitmProgramId(const ncm::ProgramId program_id) {
/* We want to mitm everything that isn't a system-module. */
if (!ncm::IsSystemProgramId(program_id)) {
return true;
@@ -81,26 +77,14 @@ namespace ams::mitm::fs {
return has_launched_qlaunch || ShouldMitmProgramId(client_info.program_id);
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(FsMitmService) { /* ... */ }
protected:
/* Overridden commands. */
Result OpenFileSystemWithPatch(sf::Out<std::shared_ptr<IFileSystemInterface>> out, ncm::ProgramId program_id, u32 _filesystem_type);
Result OpenFileSystemWithId(sf::Out<std::shared_ptr<IFileSystemInterface>> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type);
Result OpenSdCardFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> out);
Result OpenSaveDataFileSystem(sf::Out<std::shared_ptr<IFileSystemInterface>> out, u8 space_id, const ams::fs::SaveDataAttribute &attribute);
Result OpenBisStorage(sf::Out<std::shared_ptr<IStorageInterface>> out, u32 bis_partition_id);
Result OpenDataStorageByCurrentProcess(sf::Out<std::shared_ptr<IStorageInterface>> out);
Result OpenDataStorageByDataId(sf::Out<std::shared_ptr<IStorageInterface>> out, ncm::DataId data_id, u8 storage_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(OpenFileSystemWithPatch, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(OpenFileSystemWithId, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(OpenSdCardFileSystem),
MAKE_SERVICE_COMMAND_META(OpenSaveDataFileSystem),
MAKE_SERVICE_COMMAND_META(OpenBisStorage),
MAKE_SERVICE_COMMAND_META(OpenDataStorageByCurrentProcess),
MAKE_SERVICE_COMMAND_META(OpenDataStorageByDataId),
};
Result OpenFileSystemWithPatch(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, ncm::ProgramId program_id, u32 _filesystem_type);
Result OpenFileSystemWithId(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, const fssrv::sf::Path &path, ncm::ProgramId program_id, u32 _filesystem_type);
Result OpenSdCardFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out);
Result OpenSaveDataFileSystem(sf::Out<std::shared_ptr<ams::fssrv::sf::IFileSystem>> out, u8 space_id, const ams::fs::SaveDataAttribute &attribute);
Result OpenBisStorage(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, u32 bis_partition_id);
Result OpenDataStorageByCurrentProcess(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out);
Result OpenDataStorageByDataId(sf::Out<std::shared_ptr<ams::fssrv::sf::IStorage>> out, ncm::DataId data_id, u8 storage_id);
};
}

View File

@@ -78,7 +78,7 @@ namespace ams::mitm::fs {
void MitmModule::ThreadFunction(void *arg) {
/* Create fs mitm. */
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<FsMitmService>(MitmServiceName));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<IFsMitmInterface, FsMitmService>(MitmServiceName)));
/* Process for the server. */
ProcessForServerOnAllThreads();

View File

@@ -19,11 +19,18 @@
namespace ams::mitm::hid {
class HidMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
SetSupportedNpadStyleSet = 100,
};
namespace {
#define AMS_HID_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 100, Result, SetSupportedNpadStyleSet, (const sf::ClientAppletResourceUserId &client_aruid, u32 style_set))
AMS_SF_DEFINE_MITM_INTERFACE(IHidMitmInterface, AMS_HID_MITM_INTERFACE_INFO)
}
class HidMitmService : public sf::MitmServiceImplBase {
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* TODO: Remove in Atmosphere 0.10.2. */
@@ -33,14 +40,9 @@ namespace ams::mitm::hid {
return client_info.override_status.IsHbl();
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(HidMitmService) { /* ... */ }
protected:
/* Overridden commands. */
Result SetSupportedNpadStyleSet(const sf::ClientAppletResourceUserId &client_aruid, u32 style_set);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SetSupportedNpadStyleSet),
};
};
static_assert(IsIHidMitmInterface<HidMitmService>);
}

View File

@@ -59,7 +59,7 @@ namespace ams::mitm::hid {
}
/* Create hid mitm. */
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<HidMitmService>(MitmServiceName));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<IHidMitmInterface, HidMitmService>(MitmServiceName)));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -18,13 +18,20 @@
namespace ams::mitm::ns {
class NsAmMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
};
namespace impl {
#define AMS_NS_AM_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 21, Result, GetApplicationContentPath, (const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type)) \
AMS_SF_METHOD_INFO(C, H, 23, Result, ResolveApplicationContentPath, (ncm::ProgramId application_id, u8 content_type)) \
AMS_SF_METHOD_INFO(C, H, 92, Result, GetRunningApplicationProgramId, (sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id), hos::Version_6_0_0)
AMS_SF_DEFINE_MITM_INTERFACE(IAmMitmInterface, AMS_NS_AM_MITM_INTERFACE_INFO)
}
class NsAmMitmService : public sf::MitmServiceImplBase {
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* We will mitm:
@@ -33,18 +40,11 @@ namespace ams::mitm::ns {
return ncm::IsWebAppletId(client_info.program_id);
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(NsAmMitmService) { /* ... */ }
protected:
/* Actual command API. */
Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type);
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetApplicationContentPath),
MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath),
MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_6_0_0),
};
};
static_assert(impl::IsIAmMitmInterface<NsAmMitmService>);
}

View File

@@ -37,13 +37,13 @@ namespace ams::mitm::ns {
return nswebGetRunningApplicationProgramId(this->srv.get(), reinterpret_cast<u64 *>(out.GetPointer()), static_cast<u64>(application_id));
}
Result NsWebMitmService::GetDocumentInterface(sf::Out<std::shared_ptr<NsDocumentService>> out) {
Result NsWebMitmService::GetDocumentInterface(sf::Out<std::shared_ptr<impl::IDocumentInterface>> out) {
/* Open a document interface. */
NsDocumentInterface doc;
R_TRY(nsGetDocumentInterfaceFwd(this->forward_service.get(), &doc));
const sf::cmif::DomainObjectId target_object_id{serviceGetObjectId(&doc.s)};
out.SetValue(std::make_shared<NsDocumentService>(this->client_info, std::make_unique<NsDocumentInterface>(doc)), target_object_id);
out.SetValue(sf::MakeShared<impl::IDocumentInterface, NsDocumentService>(this->client_info, std::make_unique<NsDocumentInterface>(doc)), target_object_id);
return ResultSuccess();
}

View File

@@ -20,13 +20,23 @@
namespace ams::mitm::ns {
class NsDocumentService : public sf::IServiceObject {
private:
enum class CommandId {
GetApplicationContentPath = 21,
ResolveApplicationContentPath = 23,
GetRunningApplicationProgramId = 92,
};
namespace impl {
#define AMS_NS_DOCUMENT_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 21, Result, GetApplicationContentPath, (const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type)) \
AMS_SF_METHOD_INFO(C, H, 23, Result, ResolveApplicationContentPath, (ncm::ProgramId application_id, u8 content_type)) \
AMS_SF_METHOD_INFO(C, H, 92, Result, GetRunningApplicationProgramId, (sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id), hos::Version_6_0_0)
AMS_SF_DEFINE_INTERFACE(IDocumentInterface, AMS_NS_DOCUMENT_MITM_INTERFACE_INFO)
#define AMS_NS_WEB_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 7999, Result, GetDocumentInterface, (sf::Out<std::shared_ptr<IDocumentInterface>> out))
AMS_SF_DEFINE_MITM_INTERFACE(IWebMitmInterface, AMS_NS_WEB_MITM_INTERFACE_INFO)
}
class NsDocumentService {
private:
sm::MitmProcessInfo client_info;
std::unique_ptr<::NsDocumentInterface> srv;
@@ -36,24 +46,17 @@ namespace ams::mitm::ns {
virtual ~NsDocumentService() {
nsDocumentInterfaceClose(this->srv.get());
}
protected:
public:
/* Actual command API. */
Result GetApplicationContentPath(const sf::OutBuffer &out_path, ncm::ProgramId application_id, u8 content_type);
Result ResolveApplicationContentPath(ncm::ProgramId application_id, u8 content_type);
Result GetRunningApplicationProgramId(sf::Out<ncm::ProgramId> out, ncm::ProgramId application_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetApplicationContentPath),
MAKE_SERVICE_COMMAND_META(ResolveApplicationContentPath),
MAKE_SERVICE_COMMAND_META(GetRunningApplicationProgramId, hos::Version_6_0_0),
};
};
static_assert(impl::IsIDocumentInterface<NsDocumentService>);
class NsWebMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
GetDocumentInterface = 7999,
};
class NsWebMitmService : public sf::MitmServiceImplBase {
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* We will mitm:
@@ -62,13 +65,8 @@ namespace ams::mitm::ns {
return ncm::IsWebAppletId(client_info.program_id);
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(NsWebMitmService) { /* ... */ }
protected:
Result GetDocumentInterface(sf::Out<std::shared_ptr<NsDocumentService>> out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetDocumentInterface),
};
Result GetDocumentInterface(sf::Out<std::shared_ptr<impl::IDocumentInterface>> out);
};
static_assert(impl::IsIWebMitmInterface<NsWebMitmService>);
}

View File

@@ -39,9 +39,9 @@ namespace ams::mitm::ns {
/* Create mitm servers. */
if (hos::GetVersion() < hos::Version_3_0_0) {
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<NsAmMitmService>(NsAmMitmServiceName));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<impl::IAmMitmInterface, NsAmMitmService>(NsAmMitmServiceName)));
} else {
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<NsWebMitmService>(NsWebMitmServiceName));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<impl::IWebMitmInterface, NsWebMitmService>(NsWebMitmServiceName)));
}
/* Loop forever, servicing our services. */

View File

@@ -18,16 +18,23 @@
namespace ams::mitm::settings {
class SetMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
GetLanguageCode = 0,
GetRegionCode = 4,
};
namespace {
#define AMS_SETTINGS_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetLanguageCode, (sf::Out<ams::settings::LanguageCode> out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetRegionCode, (sf::Out<ams::settings::RegionCode> out))
AMS_SF_DEFINE_MITM_INTERFACE(ISetMitmInterface, AMS_SETTINGS_MITM_INTERFACE_INFO)
}
class SetMitmService : public sf::MitmServiceImplBase {
private:
os::Mutex lock{false};
cfg::OverrideLocale locale;
bool got_locale;
bool got_locale = false;
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* We will mitm:
@@ -36,20 +43,12 @@ namespace ams::mitm::settings {
const bool is_game = (ncm::IsApplicationId(client_info.program_id) && !client_info.override_status.IsHbl());
return client_info.program_id == ncm::SystemProgramId::Ns || is_game;
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(SetMitmService) {
this->got_locale = false;
}
private:
Result EnsureLocale();
protected:
public:
Result GetLanguageCode(sf::Out<ams::settings::LanguageCode> out);
Result GetRegionCode(sf::Out<ams::settings::RegionCode> out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetLanguageCode),
MAKE_SERVICE_COMMAND_META(GetRegionCode),
};
};
static_assert(IsISetMitmInterface<SetMitmService>);
}

View File

@@ -43,8 +43,8 @@ namespace ams::mitm::settings {
mitm::WaitInitialized();
/* Create mitm servers. */
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<SetMitmService>(SetMitmServiceName));
R_ABORT_UNLESS(g_server_manager.RegisterMitmServer<SetSysMitmService>(SetSysMitmServiceName));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<ISetMitmInterface, SetMitmService>(SetMitmServiceName)));
R_ABORT_UNLESS((g_server_manager.RegisterMitmServer<ISetSysMitmInterface, SetSysMitmService>(SetSysMitmServiceName)));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -18,15 +18,21 @@
namespace ams::mitm::settings {
class SetSysMitmService : public sf::IMitmServiceObject {
private:
enum class CommandId {
GetFirmwareVersion = 3,
GetFirmwareVersion2 = 4,
namespace {
GetSettingsItemValueSize = 37,
GetSettingsItemValue = 38,
};
#define AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetFirmwareVersion, (sf::Out<ams::settings::FirmwareVersion> out)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetFirmwareVersion2, (sf::Out<ams::settings::FirmwareVersion> out)) \
AMS_SF_METHOD_INFO(C, H, 37, Result, GetSettingsItemValueSize, (sf::Out<u64> out_size, const ams::settings::fwdbg::SettingsName &name, const ams::settings::fwdbg::SettingsItemKey &key)) \
AMS_SF_METHOD_INFO(C, H, 38, Result, GetSettingsItemValue, (sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::fwdbg::SettingsName &name, const ams::settings::fwdbg::SettingsItemKey &key))
AMS_SF_DEFINE_MITM_INTERFACE(ISetSysMitmInterface, AMS_SETTINGS_SYSTEM_MITM_INTERFACE_INFO)
}
class SetSysMitmService : public sf::MitmServiceImplBase {
public:
using MitmServiceImplBase::MitmServiceImplBase;
public:
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
/* We will mitm:
@@ -35,19 +41,11 @@ namespace ams::mitm::settings {
return true;
}
public:
SF_MITM_SERVICE_OBJECT_CTOR(SetSysMitmService) { /* ... */ }
protected:
Result GetFirmwareVersion(sf::Out<ams::settings::FirmwareVersion> out);
Result GetFirmwareVersion2(sf::Out<ams::settings::FirmwareVersion> out);
Result GetSettingsItemValueSize(sf::Out<u64> out_size, const ams::settings::fwdbg::SettingsName &name, const ams::settings::fwdbg::SettingsItemKey &key);
Result GetSettingsItemValue(sf::Out<u64> out_size, const sf::OutBuffer &out, const ams::settings::fwdbg::SettingsName &name, const ams::settings::fwdbg::SettingsItemKey &key);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetFirmwareVersion),
MAKE_SERVICE_COMMAND_META(GetFirmwareVersion2),
MAKE_SERVICE_COMMAND_META(GetSettingsItemValueSize),
MAKE_SERVICE_COMMAND_META(GetSettingsItemValue),
};
};
static_assert(IsISetSysMitmInterface<SetSysMitmService>);
}

View File

@@ -15,7 +15,6 @@
*/
#pragma once
#include <stratosphere.hpp>
#include "sysupdater_i_async_result.hpp"
#include "sysupdater_thread_allocator.hpp"
namespace ams::mitm::sysupdater {
@@ -59,18 +58,18 @@ namespace ams::mitm::sysupdater {
}
};
class AsyncBase : public IAsyncBase {
class AsyncBase {
public:
virtual ~AsyncBase() { /* ... */ }
static Result ToAsyncResult(Result result);
virtual Result Cancel() override final {
Result Cancel() {
this->CancelImpl();
return ResultSuccess();
}
virtual Result GetErrorContext(sf::Out<err::ErrorContext> out) override {
virtual Result GetErrorContext(sf::Out<err::ErrorContext> out) {
*out = {};
return ResultSuccess();
}
@@ -78,29 +77,17 @@ namespace ams::mitm::sysupdater {
virtual void CancelImpl() = 0;
};
class AsyncResultBase : public IAsyncResult {
class AsyncResultBase : public AsyncBase {
public:
virtual ~AsyncResultBase() { /* ... */ }
static Result ToAsyncResult(Result result) { return AsyncBase::ToAsyncResult(result); }
virtual Result Cancel() override final {
this->CancelImpl();
return ResultSuccess();
}
virtual Result Get() override final {
Result Get() {
return ToAsyncResult(this->GetImpl());
}
virtual Result GetErrorContext(sf::Out<err::ErrorContext> out) override {
*out = {};
return ResultSuccess();
}
private:
virtual void CancelImpl() = 0;
virtual Result GetImpl() = 0;
};
static_assert(ns::impl::IsIAsyncResult<AsyncResultBase>);
/* NOTE: Based off of ns AsyncPrepareCardUpdateImpl. */
/* We don't implement the RequestServer::ManagedStop details, as we don't implement stoppable request list. */

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
namespace ams::mitm::sysupdater {
class IAsyncBase : public sf::IServiceObject {
public:
virtual Result Cancel() = 0;
virtual Result GetErrorContext(sf::Out<err::ErrorContext> out) = 0;
};
class IAsyncResult : public IAsyncBase {
private:
enum class CommandId {
Get = 0,
Cancel = 1,
GetErrorContext = 2,
};
public:
virtual Result Get() = 0;
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(Get),
MAKE_SERVICE_COMMAND_META(Cancel),
MAKE_SERVICE_COMMAND_META(GetErrorContext),
};
};
}

View File

@@ -50,7 +50,7 @@ namespace ams::mitm::sysupdater {
ON_SCOPE_EXIT { nim::FinalizeForNetworkInstallManager(); };
/* Register ams:su. */
R_ABORT_UNLESS((g_server_manager.RegisterServer<sysupdater::SystemUpdateService>(SystemUpdateServiceName, SystemUpdateMaxSessions, sf::ServiceObjectTraits<sysupdater::SystemUpdateService>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_system_update_service_object)))));
R_ABORT_UNLESS((g_server_manager.RegisterServer<sysupdater::impl::ISystemUpdateInterface, sysupdater::SystemUpdateService>(SystemUpdateServiceName, SystemUpdateMaxSessions, sf::GetSharedPointerTo<sysupdater::impl::ISystemUpdateInterface>(g_system_update_service_object))));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -411,21 +411,21 @@ namespace ams::mitm::sysupdater {
return this->SetupUpdateImpl(transfer_memory.GetValue(), transfer_memory_size, path, exfat, firmware_variation_id);
}
Result SystemUpdateService::RequestPrepareUpdate(sf::OutCopyHandle out_event_handle, sf::Out<std::shared_ptr<IAsyncResult>> out_async) {
Result SystemUpdateService::RequestPrepareUpdate(sf::OutCopyHandle out_event_handle, sf::Out<std::shared_ptr<ns::impl::IAsyncResult>> out_async) {
/* Ensure the update is setup but not prepared. */
R_UNLESS(this->setup_update, ns::ResultCardUpdateNotSetup());
R_UNLESS(!this->requested_update, ns::ResultPrepareCardUpdateAlreadyRequested());
/* Create the async result. */
auto async_result = std::make_shared<AsyncPrepareSdCardUpdateImpl>(std::addressof(*this->update_task));
auto async_result = sf::MakeShared<ns::impl::IAsyncResult, AsyncPrepareSdCardUpdateImpl>(std::addressof(*this->update_task));
R_UNLESS(async_result != nullptr, ns::ResultOutOfMaxRunningTask());
/* Run the task. */
R_TRY(async_result->Run());
R_TRY(async_result->GetImpl().Run());
/* We prepared the task! */
this->requested_update = true;
out_event_handle.SetValue(async_result->GetEvent().GetReadableHandle());
out_event_handle.SetValue(async_result->GetImpl().GetEvent().GetReadableHandle());
out_async.SetValue(std::move(async_result));
return ResultSuccess();

View File

@@ -15,7 +15,6 @@
*/
#pragma once
#include <stratosphere.hpp>
#include "sysupdater_i_async_result.hpp"
#include "sysupdater_apply_manager.hpp"
namespace ams::mitm::sysupdater {
@@ -39,18 +38,25 @@ namespace ams::mitm::sysupdater {
s64 total_size;
};
class SystemUpdateService final : public sf::IServiceObject {
private:
enum class CommandId {
GetUpdateInformation = 0,
ValidateUpdate = 1,
SetupUpdate = 2,
SetupUpdateWithVariation = 3,
RequestPrepareUpdate = 4,
GetPrepareUpdateProgress = 5,
HasPreparedUpdate = 6,
ApplyPreparedUpdate = 7,
};
namespace impl {
#define AMS_SYSUPDATER_SYSTEM_UPDATE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetUpdateInformation, (sf::Out<UpdateInformation> out, const ncm::Path &path)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, ValidateUpdate, (sf::Out<Result> out_validate_result, sf::Out<UpdateValidationInfo> out_validate_info, const ncm::Path &path)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, SetupUpdate, (sf::CopyHandle transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, SetupUpdateWithVariation, (sf::CopyHandle transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat, ncm::FirmwareVariationId firmware_variation_id)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, RequestPrepareUpdate, (sf::OutCopyHandle out_event_handle, sf::Out<std::shared_ptr<ns::impl::IAsyncResult>> out_async)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, GetPrepareUpdateProgress, (sf::Out<SystemUpdateProgress> out)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, HasPreparedUpdate, (sf::Out<bool> out)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, ApplyPreparedUpdate, ())
AMS_SF_DEFINE_INTERFACE(ISystemUpdateInterface, AMS_SYSUPDATER_SYSTEM_UPDATE_INTERFACE_INFO)
}
class SystemUpdateService final {
private:
SystemUpdateApplyManager apply_manager;
std::optional<ncm::PackageSystemDowngradeTask> update_task;
@@ -62,26 +68,16 @@ namespace ams::mitm::sysupdater {
private:
Result SetupUpdateImpl(os::ManagedHandle transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat, ncm::FirmwareVariationId firmware_variation_id);
Result InitializeUpdateTask(os::ManagedHandle &transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat, ncm::FirmwareVariationId firmware_variation_id);
private:
public:
Result GetUpdateInformation(sf::Out<UpdateInformation> out, const ncm::Path &path);
Result ValidateUpdate(sf::Out<Result> out_validate_result, sf::Out<UpdateValidationInfo> out_validate_info, const ncm::Path &path);
Result SetupUpdate(sf::CopyHandle transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat);
Result SetupUpdateWithVariation(sf::CopyHandle transfer_memory, u64 transfer_memory_size, const ncm::Path &path, bool exfat, ncm::FirmwareVariationId firmware_variation_id);
Result RequestPrepareUpdate(sf::OutCopyHandle out_event_handle, sf::Out<std::shared_ptr<IAsyncResult>> out_async);
Result RequestPrepareUpdate(sf::OutCopyHandle out_event_handle, sf::Out<std::shared_ptr<ns::impl::IAsyncResult>> out_async);
Result GetPrepareUpdateProgress(sf::Out<SystemUpdateProgress> out);
Result HasPreparedUpdate(sf::Out<bool> out);
Result ApplyPreparedUpdate();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetUpdateInformation),
MAKE_SERVICE_COMMAND_META(ValidateUpdate),
MAKE_SERVICE_COMMAND_META(SetupUpdate),
MAKE_SERVICE_COMMAND_META(SetupUpdateWithVariation),
MAKE_SERVICE_COMMAND_META(RequestPrepareUpdate),
MAKE_SERVICE_COMMAND_META(GetPrepareUpdateProgress),
MAKE_SERVICE_COMMAND_META(HasPreparedUpdate),
MAKE_SERVICE_COMMAND_META(ApplyPreparedUpdate),
};
};
static_assert(impl::IsISystemUpdateInterface<SystemUpdateService>);
}

View File

@@ -18,43 +18,42 @@
namespace ams::dmnt::cheat {
class CheatService final : public sf::IServiceObject {
private:
enum class CommandId {
/* Meta */
HasCheatProcess = 65000,
GetCheatProcessEvent = 65001,
GetCheatProcessMetadata = 65002,
ForceOpenCheatProcess = 65003,
PauseCheatProcess = 65004,
ResumeCheatProcess = 65005,
/* TODO: In libstratosphere, eventually? */
namespace impl {
/* Interact with Memory */
GetCheatProcessMappingCount = 65100,
GetCheatProcessMappings = 65101,
ReadCheatProcessMemory = 65102,
WriteCheatProcessMemory = 65103,
QueryCheatProcessMemory = 65104,
#define AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 65000, void, HasCheatProcess, (sf::Out<bool> out)) \
AMS_SF_METHOD_INFO(C, H, 65001, void, GetCheatProcessEvent, (sf::OutCopyHandle out_event)) \
AMS_SF_METHOD_INFO(C, H, 65002, Result, GetCheatProcessMetadata, (sf::Out<CheatProcessMetadata> out_metadata)) \
AMS_SF_METHOD_INFO(C, H, 65003, Result, ForceOpenCheatProcess, ()) \
AMS_SF_METHOD_INFO(C, H, 65004, Result, PauseCheatProcess, ()) \
AMS_SF_METHOD_INFO(C, H, 65005, Result, ResumeCheatProcess, ()) \
AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out<u64> out_count)) \
AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset)) \
AMS_SF_METHOD_INFO(C, H, 65102, Result, ReadCheatProcessMemory, (const sf::OutBuffer &buffer, u64 address, u64 out_size)) \
AMS_SF_METHOD_INFO(C, H, 65103, Result, WriteCheatProcessMemory, (const sf::InBuffer &buffer, u64 address, u64 in_size)) \
AMS_SF_METHOD_INFO(C, H, 65104, Result, QueryCheatProcessMemory, (sf::Out<MemoryInfo> mapping, u64 address)) \
AMS_SF_METHOD_INFO(C, H, 65200, Result, GetCheatCount, (sf::Out<u64> out_count)) \
AMS_SF_METHOD_INFO(C, H, 65201, Result, GetCheats, (const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset)) \
AMS_SF_METHOD_INFO(C, H, 65202, Result, GetCheatById, (sf::Out<CheatEntry> cheat, u32 cheat_id)) \
AMS_SF_METHOD_INFO(C, H, 65203, Result, ToggleCheat, (u32 cheat_id)) \
AMS_SF_METHOD_INFO(C, H, 65204, Result, AddCheat, (const CheatDefinition &cheat, sf::Out<u32> out_cheat_id, bool enabled)) \
AMS_SF_METHOD_INFO(C, H, 65205, Result, RemoveCheat, (u32 cheat_id)) \
AMS_SF_METHOD_INFO(C, H, 65206, Result, ReadStaticRegister, (sf::Out<u64> out, u8 which)) \
AMS_SF_METHOD_INFO(C, H, 65207, Result, WriteStaticRegister, (u8 which, u64 value)) \
AMS_SF_METHOD_INFO(C, H, 65208, Result, ResetStaticRegisters, ()) \
AMS_SF_METHOD_INFO(C, H, 65300, Result, GetFrozenAddressCount, (sf::Out<u64> out_count)) \
AMS_SF_METHOD_INFO(C, H, 65301, Result, GetFrozenAddresses, (const sf::OutArray<FrozenAddressEntry> &addresses, sf::Out<u64> out_count, u64 offset)) \
AMS_SF_METHOD_INFO(C, H, 65302, Result, GetFrozenAddress, (sf::Out<FrozenAddressEntry> entry, u64 address)) \
AMS_SF_METHOD_INFO(C, H, 65303, Result, EnableFrozenAddress, (sf::Out<u64> out_value, u64 address, u64 width)) \
AMS_SF_METHOD_INFO(C, H, 65304, Result, DisableFrozenAddress, (u64 address))
/* Interact with Cheats */
GetCheatCount = 65200,
GetCheats = 65201,
GetCheatById = 65202,
ToggleCheat = 65203,
AddCheat = 65204,
RemoveCheat = 65205,
ReadStaticRegister = 65206,
WriteStaticRegister = 65207,
ResetStaticRegisters = 65208,
AMS_SF_DEFINE_INTERFACE(ICheatInterface, AMS_DMNT_I_CHEAT_INTERFACE_INTERFACE_INFO)
/* Interact with Frozen Addresses */
GetFrozenAddressCount = 65300,
GetFrozenAddresses = 65301,
GetFrozenAddress = 65302,
EnableFrozenAddress = 65303,
DisableFrozenAddress = 65304,
};
private:
}
class CheatService final {
public:
void HasCheatProcess(sf::Out<bool> out);
void GetCheatProcessEvent(sf::OutCopyHandle out_event);
Result GetCheatProcessMetadata(sf::Out<CheatProcessMetadata> out_metadata);
@@ -83,38 +82,7 @@ namespace ams::dmnt::cheat {
Result GetFrozenAddress(sf::Out<FrozenAddressEntry> entry, u64 address);
Result EnableFrozenAddress(sf::Out<u64> out_value, u64 address, u64 width);
Result DisableFrozenAddress(u64 address);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(HasCheatProcess),
MAKE_SERVICE_COMMAND_META(GetCheatProcessEvent),
MAKE_SERVICE_COMMAND_META(GetCheatProcessMetadata),
MAKE_SERVICE_COMMAND_META(ForceOpenCheatProcess),
MAKE_SERVICE_COMMAND_META(PauseCheatProcess),
MAKE_SERVICE_COMMAND_META(ResumeCheatProcess),
MAKE_SERVICE_COMMAND_META(GetCheatProcessMappingCount),
MAKE_SERVICE_COMMAND_META(GetCheatProcessMappings),
MAKE_SERVICE_COMMAND_META(ReadCheatProcessMemory),
MAKE_SERVICE_COMMAND_META(WriteCheatProcessMemory),
MAKE_SERVICE_COMMAND_META(QueryCheatProcessMemory),
MAKE_SERVICE_COMMAND_META(GetCheatCount),
MAKE_SERVICE_COMMAND_META(GetCheats),
MAKE_SERVICE_COMMAND_META(GetCheatById),
MAKE_SERVICE_COMMAND_META(ToggleCheat),
MAKE_SERVICE_COMMAND_META(AddCheat),
MAKE_SERVICE_COMMAND_META(RemoveCheat),
MAKE_SERVICE_COMMAND_META(ReadStaticRegister),
MAKE_SERVICE_COMMAND_META(WriteStaticRegister),
MAKE_SERVICE_COMMAND_META(ResetStaticRegisters),
MAKE_SERVICE_COMMAND_META(GetFrozenAddressCount),
MAKE_SERVICE_COMMAND_META(GetFrozenAddresses),
MAKE_SERVICE_COMMAND_META(GetFrozenAddress),
MAKE_SERVICE_COMMAND_META(EnableFrozenAddress),
MAKE_SERVICE_COMMAND_META(DisableFrozenAddress),
};
};
static_assert(impl::IsICheatInterface<CheatService>);
}

View File

@@ -140,7 +140,7 @@ int main(int argc, char **argv)
/* Create services. */
/* TODO: Implement rest of dmnt:- in ams.tma development branch. */
/* R_ABORT_UNLESS((g_server_manager.RegisterServer<dmnt::cheat::CheatService>(DebugMonitorServiceName, DebugMonitorMaxSessions))); */
R_ABORT_UNLESS((g_server_manager.RegisterServer<dmnt::cheat::CheatService>(CheatServiceName, CheatMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<dmnt::cheat::impl::ICheatInterface, dmnt::cheat::CheatService>(CheatServiceName, CheatMaxSessions)));
/* Loop forever, servicing our services. */
/* Nintendo loops four threads processing on the manager -- we'll loop an extra fifth for our cheat service. */

View File

@@ -57,7 +57,8 @@ namespace ams::dmnt {
static_assert(util::is_pod<TargetIOFileHandle>::value && sizeof(TargetIOFileHandle) == sizeof(u64), "TargetIOFileHandle");
class DebugMonitorService final : public sf::IServiceObject {
/* TODO: Convert to new sf format in the future. */
class DebugMonitorService final {
private:
enum class CommandId {
BreakDebugProcess = 0,
@@ -131,61 +132,6 @@ namespace ams::dmnt {
Result TargetIO_FileSetSize(const sf::InBuffer &input, s64 size);
Result TargetIO_FileDelete(const sf::InBuffer &path);
Result TargetIO_FileMove(const sf::InBuffer &src_path, const sf::InBuffer &dst_path);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(BreakDebugProcess),
MAKE_SERVICE_COMMAND_META(TerminateDebugProcess),
MAKE_SERVICE_COMMAND_META(CloseHandle),
// MAKE_SERVICE_COMMAND_META(LoadImage),
MAKE_SERVICE_COMMAND_META(GetProcessId),
MAKE_SERVICE_COMMAND_META(GetProcessHandle),
MAKE_SERVICE_COMMAND_META(WaitSynchronization),
//MAKE_SERVICE_COMMAND_META(GetDebugEvent),
// MAKE_SERVICE_COMMAND_META(GetProcessModuleInfo),
// MAKE_SERVICE_COMMAND_META(GetProcessList),
// MAKE_SERVICE_COMMAND_META(GetThreadList),
// MAKE_SERVICE_COMMAND_META(GetDebugThreadContext),
// MAKE_SERVICE_COMMAND_META(ContinueDebugEvent),
// MAKE_SERVICE_COMMAND_META(ReadDebugProcessMemory),
// MAKE_SERVICE_COMMAND_META(WriteDebugProcessMemory),
// MAKE_SERVICE_COMMAND_META(SetDebugThreadContext),
// MAKE_SERVICE_COMMAND_META(GetDebugThreadParam),
// MAKE_SERVICE_COMMAND_META(InitializeThreadInfo),
// MAKE_SERVICE_COMMAND_META(SetHardwareBreakPoint),
// MAKE_SERVICE_COMMAND_META(QueryDebugProcessMemory),
// MAKE_SERVICE_COMMAND_META(GetProcessMemoryDetails),
// MAKE_SERVICE_COMMAND_META(AttachByProgramId),
// MAKE_SERVICE_COMMAND_META(AttachOnLaunch),
// MAKE_SERVICE_COMMAND_META(GetDebugMonitorProcessId),
// MAKE_SERVICE_COMMAND_META(GetJitDebugProcessList),
// MAKE_SERVICE_COMMAND_META(CreateCoreDump),
// MAKE_SERVICE_COMMAND_META(GetAllDebugThreadInfo),
MAKE_SERVICE_COMMAND_META(TargetIO_FileOpen),
MAKE_SERVICE_COMMAND_META(TargetIO_FileClose),
MAKE_SERVICE_COMMAND_META(TargetIO_FileRead),
MAKE_SERVICE_COMMAND_META(TargetIO_FileWrite),
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetAttributes),
MAKE_SERVICE_COMMAND_META(TargetIO_FileGetInformation),
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetTime),
MAKE_SERVICE_COMMAND_META(TargetIO_FileSetSize),
MAKE_SERVICE_COMMAND_META(TargetIO_FileDelete),
MAKE_SERVICE_COMMAND_META(TargetIO_FileMove),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryCreate),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryDelete),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryRename),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryGetCount),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryOpen),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryGetNext),
// MAKE_SERVICE_COMMAND_META(TargetIO_DirectoryClose),
// MAKE_SERVICE_COMMAND_META(TargetIO_GetFreeSpace),
// MAKE_SERVICE_COMMAND_META(TargetIO_GetVolumeInformation),
// MAKE_SERVICE_COMMAND_META(InitiateCoreDump),
// MAKE_SERVICE_COMMAND_META(ContinueCoreDump),
// MAKE_SERVICE_COMMAND_META(AddTTYToCoreDump),
// MAKE_SERVICE_COMMAND_META(AddImageToCoreDump),
// MAKE_SERVICE_COMMAND_META(CloseCoreDump),
// MAKE_SERVICE_COMMAND_META(CancelAttach),
};
};
}

View File

@@ -156,11 +156,10 @@ int main(int argc, char **argv)
fatal::srv::CheckRepairStatus();
/* Create services. */
R_ABORT_UNLESS((g_server_manager.RegisterServer<fatal::srv::PrivateService>(PrivateServiceName, PrivateMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<fatal::srv::UserService>(UserServiceName, UserMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<fatal::impl::IPrivateService, fatal::srv::PrivateService>(PrivateServiceName, PrivateMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<fatal::impl::IService, fatal::srv::Service>(UserServiceName, UserMaxSessions)));
/* Add dirty event holder. */
/* TODO: s_server_manager.AddWaitable(ams::fatal::srv::GetFatalDirtyEvent()); */
auto *dirty_event_holder = ams::fatal::srv::GetFatalDirtyWaitableHolder();
g_server_manager.AddUserWaitableHolder(dirty_event_holder);

View File

@@ -133,15 +133,15 @@ namespace ams::fatal::srv {
return g_context.ThrowFatalWithPolicy(result, os::GetCurrentProcessId(), FatalPolicy_ErrorScreen);
}
Result UserService::ThrowFatal(Result result, const sf::ClientProcessId &client_pid) {
Result Service::ThrowFatal(Result result, const sf::ClientProcessId &client_pid) {
return g_context.ThrowFatal(result, client_pid.GetValue());
}
Result UserService::ThrowFatalWithPolicy(Result result, const sf::ClientProcessId &client_pid, FatalPolicy policy) {
Result Service::ThrowFatalWithPolicy(Result result, const sf::ClientProcessId &client_pid, FatalPolicy policy) {
return g_context.ThrowFatalWithPolicy(result, client_pid.GetValue(), policy);
}
Result UserService::ThrowFatalWithCpuContext(Result result, const sf::ClientProcessId &client_pid, FatalPolicy policy, const CpuContext &cpu_ctx) {
Result Service::ThrowFatalWithCpuContext(Result result, const sf::ClientProcessId &client_pid, FatalPolicy policy, const CpuContext &cpu_ctx) {
return g_context.ThrowFatalWithCpuContext(result, client_pid.GetValue(), policy, cpu_ctx);
}

View File

@@ -18,39 +18,19 @@
namespace ams::fatal::srv {
class UserService final : public sf::IServiceObject {
private:
enum class CommandId {
ThrowFatal = 0,
ThrowFatalWithPolicy = 1,
ThrowFatalWithCpuContext = 2,
};
private:
/* Actual commands. */
class Service final {
public:
Result ThrowFatal(Result error, const sf::ClientProcessId &client_pid);
Result ThrowFatalWithPolicy(Result error, const sf::ClientProcessId &client_pid, FatalPolicy policy);
Result ThrowFatalWithCpuContext(Result error, const sf::ClientProcessId &client_pid, FatalPolicy policy, const CpuContext &cpu_ctx);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(ThrowFatal),
MAKE_SERVICE_COMMAND_META(ThrowFatalWithPolicy),
MAKE_SERVICE_COMMAND_META(ThrowFatalWithCpuContext),
};
};
static_assert(fatal::impl::IsIService<Service>);
class PrivateService final : public sf::IServiceObject {
private:
enum class CommandId {
GetFatalEvent = 0,
};
private:
/* Actual commands. */
Result GetFatalEvent(sf::OutCopyHandle out_h);
class PrivateService final {
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetFatalEvent),
};
Result GetFatalEvent(sf::OutCopyHandle out_h);
};
static_assert(fatal::impl::IsIPrivateService<PrivateService>);
}

View File

@@ -18,101 +18,27 @@
namespace ams::ldr {
class LoaderService : public sf::IServiceObject {
protected:
class LoaderService final {
public:
/* Official commands. */
virtual Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle reslimit_h);
virtual Result GetProgramInfo(sf::Out<ProgramInfo> out_program_info, const ncm::ProgramLocation &loc);
virtual Result PinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc);
virtual Result UnpinProgram(PinId id);
virtual Result SetProgramArguments(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size);
virtual Result FlushArguments();
virtual Result GetProcessModuleInfo(sf::Out<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id);
virtual Result SetEnabledProgramVerification(bool enabled);
Result CreateProcess(sf::OutMoveHandle proc_h, PinId id, u32 flags, sf::CopyHandle reslimit_h);
Result GetProgramInfo(sf::Out<ProgramInfo> out_program_info, const ncm::ProgramLocation &loc);
Result PinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc);
Result UnpinProgram(PinId id);
Result SetProgramArguments(ncm::ProgramId program_id, const sf::InPointerBuffer &args, u32 args_size);
Result FlushArguments();
Result GetProcessModuleInfo(sf::Out<u32> count, const sf::OutPointerArray<ModuleInfo> &out, os::ProcessId process_id);
Result SetEnabledProgramVerification(bool enabled);
/* Atmosphere commands. */
virtual Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id);
virtual void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id);
virtual void AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
virtual Result AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc);
virtual Result AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
Result AtmosphereRegisterExternalCode(sf::OutMoveHandle out, ncm::ProgramId program_id);
void AtmosphereUnregisterExternalCode(ncm::ProgramId program_id);
void AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
Result AtmosphereGetProgramInfo(sf::Out<ProgramInfo> out_program_info, sf::Out<cfg::OverrideStatus> out_status, const ncm::ProgramLocation &loc);
Result AtmospherePinProgram(sf::Out<PinId> out_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status);
};
namespace pm {
class ProcessManagerInterface final : public LoaderService {
protected:
enum class CommandId {
CreateProcess = 0,
GetProgramInfo = 1,
PinProgram = 2,
UnpinProgram = 3,
SetEnabledProgramVerification = 4,
AtmosphereHasLaunchedProgram = 65000,
AtmosphereGetProgramInfo = 65001,
AtmospherePinProgram = 65002,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(CreateProcess),
MAKE_SERVICE_COMMAND_META(GetProgramInfo),
MAKE_SERVICE_COMMAND_META(PinProgram),
MAKE_SERVICE_COMMAND_META(UnpinProgram),
MAKE_SERVICE_COMMAND_META(SetEnabledProgramVerification, hos::Version_10_0_0),
MAKE_SERVICE_COMMAND_META(AtmosphereHasLaunchedProgram),
MAKE_SERVICE_COMMAND_META(AtmosphereGetProgramInfo),
MAKE_SERVICE_COMMAND_META(AtmospherePinProgram),
};
};
}
namespace dmnt {
class DebugMonitorInterface final : public LoaderService {
protected:
enum class CommandId {
SetProgramArguments = 0,
FlushArguments = 1,
GetProcessModuleInfo = 2,
AtmosphereHasLaunchedProgram = 65000,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SetProgramArguments),
MAKE_SERVICE_COMMAND_META(FlushArguments),
MAKE_SERVICE_COMMAND_META(GetProcessModuleInfo),
MAKE_SERVICE_COMMAND_META(AtmosphereHasLaunchedProgram),
};
};
}
namespace shell {
class ShellInterface final : public LoaderService {
protected:
enum class CommandId {
SetProgramArguments = 0,
FlushArguments = 1,
AtmosphereRegisterExternalCode = 65000,
AtmosphereUnregisterExternalCode = 65001,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(SetProgramArguments),
MAKE_SERVICE_COMMAND_META(FlushArguments),
MAKE_SERVICE_COMMAND_META(AtmosphereRegisterExternalCode),
MAKE_SERVICE_COMMAND_META(AtmosphereUnregisterExternalCode),
};
};
}
static_assert(ams::ldr::impl::IsIProcessManagerInterface<LoaderService>);
static_assert(ams::ldr::impl::IsIDebugMonitorInterface<LoaderService>);
static_assert(ams::ldr::impl::IsIShellInterface<LoaderService>);
}

View File

@@ -129,9 +129,9 @@ int main(int argc, char **argv)
ldr::SetDevelopmentForAcidSignatureCheck(spl::IsDevelopment());
/* Add services to manager. */
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::pm::ProcessManagerInterface>(ProcessManagerServiceName, ProcessManagerMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::shell::ShellInterface>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::dmnt::DebugMonitorInterface>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IProcessManagerInterface, ldr::LoaderService>(ProcessManagerServiceName, ProcessManagerMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IShellInterface, ldr::LoaderService>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ldr::impl::IDebugMonitorInterface, ldr::LoaderService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -153,24 +153,21 @@ namespace {
class ContentManagerServerManager : public sf::hipc::ServerManager<ContentManagerNumServers, ContentManagerServerOptions, ContentManagerMaxSessions> {
private:
using ServiceType = ncm::ContentManagerImpl;
using Interface = ncm::IContentManager;
using ServiceImpl = ncm::ContentManagerImpl;
private:
os::ThreadType thread;
std::shared_ptr<ServiceType> ncm_manager;
std::shared_ptr<Interface> ncm_manager;
private:
static void ThreadFunction(void *_this) {
reinterpret_cast<ContentManagerServerManager *>(_this)->LoopProcess();
}
public:
ContentManagerServerManager(ServiceType *m)
: ncm_manager()
{
/* ... */
}
ContentManagerServerManager() : ncm_manager() { /* ... */ }
ams::Result Initialize(std::shared_ptr<ServiceType> manager_obj) {
ams::Result Initialize(std::shared_ptr<Interface> manager_obj) {
this->ncm_manager = manager_obj;
return this->RegisterServer<ServiceType>(ContentManagerServiceName, ContentManagerManagerSessions, this->ncm_manager);
return this->RegisterServer<Interface, ServiceImpl>(ContentManagerServiceName, ContentManagerManagerSessions, this->ncm_manager);
}
ams::Result StartThreads() {
@@ -200,23 +197,20 @@ namespace {
class LocationResolverServerManager : public sf::hipc::ServerManager<LocationResolverNumServers, LocationResolverServerOptions, LocationResolverMaxSessions> {
private:
using ServiceType = lr::LocationResolverManagerImpl;
using Interface = lr::ILocationResolverManager;
using ServiceImpl = lr::LocationResolverManagerImpl;
private:
os::ThreadType thread;
std::shared_ptr<ServiceType> lr_manager;
std::shared_ptr<Interface> lr_manager;
private:
static void ThreadFunction(void *_this) {
reinterpret_cast<LocationResolverServerManager *>(_this)->LoopProcess();
}
public:
LocationResolverServerManager(ServiceType *m)
: lr_manager(sf::ServiceObjectTraits<ServiceType>::SharedPointerHelper::GetEmptyDeleteSharedPointer(m))
{
/* ... */
}
LocationResolverServerManager(ServiceImpl &m) : lr_manager(sf::GetSharedPointerTo<Interface>(m)) { /* ... */ }
ams::Result Initialize() {
return this->RegisterServer<ServiceType>(LocationResolverServiceName, LocationResolverManagerSessions, this->lr_manager);
return this->RegisterServer<Interface, ServiceImpl>(LocationResolverServiceName, LocationResolverManagerSessions, this->lr_manager);
}
ams::Result StartThreads() {
@@ -232,14 +226,10 @@ namespace {
};
ncm::ContentManagerImpl g_ncm_manager_service_object;
ContentManagerServerManager g_ncm_server_manager(std::addressof(g_ncm_manager_service_object));
ContentManagerServerManager g_ncm_server_manager;
lr::LocationResolverManagerImpl g_lr_manager_service_object;
LocationResolverServerManager g_lr_server_manager(std::addressof(g_lr_manager_service_object));
ALWAYS_INLINE std::shared_ptr<ncm::ContentManagerImpl> GetSharedPointerToContentManager() {
return sf::ServiceObjectTraits<ncm::ContentManagerImpl>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_ncm_manager_service_object));
}
LocationResolverServerManager g_lr_server_manager(g_lr_manager_service_object);
/* Compile-time configuration. */
#ifdef NCM_BUILD_FOR_INTITIALIZE
@@ -270,8 +260,8 @@ int main(int argc, char **argv)
AMS_ASSERT(os::GetThreadPriority(os::GetCurrentThread()) == AMS_GET_SYSTEM_THREAD_PRIORITY(ncm, MainWaitThreads));
/* Create and initialize the content manager. */
auto content_manager = GetSharedPointerToContentManager();
R_ABORT_UNLESS(content_manager->Initialize(ManagerConfig));
auto content_manager = sf::GetSharedPointerTo<ncm::IContentManager>(g_ncm_manager_service_object);
R_ABORT_UNLESS(content_manager->GetImpl().Initialize(ManagerConfig));
/* Initialize ncm's server and start threads. */
R_ABORT_UNLESS(g_ncm_server_manager.Initialize(content_manager));

View File

@@ -66,12 +66,8 @@ namespace ams::pgl {
constinit pgl::srv::ShellInterface g_shell_interface;
ALWAYS_INLINE std::shared_ptr<pgl::srv::ShellInterface> GetSharedPointerToShellInterface() {
return ams::sf::ServiceObjectTraits<pgl::srv::ShellInterface>::SharedPointerHelper::GetEmptyDeleteSharedPointer(std::addressof(g_shell_interface));
}
void RegisterServiceSession() {
R_ABORT_UNLESS(g_server_manager.RegisterServer<pgl::srv::ShellInterface>(ShellServiceName, ShellMaxSessions, GetSharedPointerToShellInterface()));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pgl::sf::IShellInterface, pgl::srv::ShellInterface>(ShellServiceName, ShellMaxSessions, ams::sf::GetSharedPointerTo<pgl::sf::IShellInterface>(g_shell_interface))));
}
void LoopProcess() {

View File

@@ -16,7 +16,7 @@
#include <stratosphere.hpp>
#include "pm_boot_mode_service.hpp"
namespace ams::pm::bm {
namespace ams::pm {
namespace {
@@ -26,12 +26,16 @@ namespace ams::pm::bm {
}
/* Override of weakly linked boot_mode_api functions. */
BootMode GetBootMode() {
return g_boot_mode;
}
namespace bm {
BootMode GetBootMode() {
return g_boot_mode;
}
void SetMaintenanceBoot() {
g_boot_mode = BootMode::Maintenance;
}
void SetMaintenanceBoot() {
g_boot_mode = BootMode::Maintenance;
}
/* Service command implementations. */

View File

@@ -16,23 +16,13 @@
#pragma once
#include <stratosphere.hpp>
namespace ams::pm::bm {
namespace ams::pm {
class BootModeService final : public sf::IServiceObject {
private:
enum class CommandId {
GetBootMode = 0,
SetMaintenanceBoot = 1,
};
private:
/* Actual command implementations. */
class BootModeService final {
public:
void GetBootMode(sf::Out<u32> out);
void SetMaintenanceBoot();
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetBootMode),
MAKE_SERVICE_COMMAND_META(SetMaintenanceBoot),
};
};
static_assert(pm::impl::IsIBootModeInterface<BootModeService>);
}

View File

@@ -17,49 +17,49 @@
#include "pm_debug_monitor_service.hpp"
#include "impl/pm_process_manager.hpp"
namespace ams::pm::dmnt {
namespace ams::pm {
/* Actual command implementations. */
Result DebugMonitorServiceBase::GetModuleIdList(sf::Out<u32> out_count, const sf::OutBuffer &out_buf, u64 unused) {
Result DebugMonitorService::GetModuleIdList(sf::Out<u32> out_count, const sf::OutBuffer &out_buf, u64 unused) {
R_UNLESS(out_buf.GetSize() <= std::numeric_limits<s32>::max(), pm::ResultInvalidSize());
return impl::GetModuleIdList(out_count.GetPointer(), out_buf.GetPointer(), out_buf.GetSize(), unused);
}
Result DebugMonitorServiceBase::GetExceptionProcessIdList(sf::Out<u32> out_count, const sf::OutArray<os::ProcessId> &out_process_ids) {
Result DebugMonitorService::GetExceptionProcessIdList(sf::Out<u32> out_count, const sf::OutArray<os::ProcessId> &out_process_ids) {
R_UNLESS(out_process_ids.GetSize() <= std::numeric_limits<s32>::max(), pm::ResultInvalidSize());
return impl::GetExceptionProcessIdList(out_count.GetPointer(), out_process_ids.GetPointer(), out_process_ids.GetSize());
}
Result DebugMonitorServiceBase::StartProcess(os::ProcessId process_id) {
Result DebugMonitorService::StartProcess(os::ProcessId process_id) {
return impl::StartProcess(process_id);
}
Result DebugMonitorServiceBase::GetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id) {
Result DebugMonitorService::GetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id) {
return impl::GetProcessId(out.GetPointer(), program_id);
}
Result DebugMonitorServiceBase::HookToCreateProcess(sf::OutCopyHandle out_hook, ncm::ProgramId program_id) {
Result DebugMonitorService::HookToCreateProcess(sf::OutCopyHandle out_hook, ncm::ProgramId program_id) {
return impl::HookToCreateProcess(out_hook.GetHandlePointer(), program_id);
}
Result DebugMonitorServiceBase::GetApplicationProcessId(sf::Out<os::ProcessId> out) {
Result DebugMonitorService::GetApplicationProcessId(sf::Out<os::ProcessId> out) {
return impl::GetApplicationProcessId(out.GetPointer());
}
Result DebugMonitorServiceBase::HookToCreateApplicationProcess(sf::OutCopyHandle out_hook) {
Result DebugMonitorService::HookToCreateApplicationProcess(sf::OutCopyHandle out_hook) {
return impl::HookToCreateApplicationProcess(out_hook.GetHandlePointer());
}
Result DebugMonitorServiceBase::ClearHook(u32 which) {
Result DebugMonitorService::ClearHook(u32 which) {
return impl::ClearHook(which);
}
/* Atmosphere extension commands. */
Result DebugMonitorServiceBase::AtmosphereGetProcessInfo(sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {
Result DebugMonitorService::AtmosphereGetProcessInfo(sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id) {
return impl::AtmosphereGetProcessInfo(out_process_handle.GetHandlePointer(), out_loc.GetPointer(), out_status.GetPointer(), process_id);
}
Result DebugMonitorServiceBase::AtmosphereGetCurrentLimitInfo(sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource) {
Result DebugMonitorService::AtmosphereGetCurrentLimitInfo(sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource) {
return impl::AtmosphereGetCurrentLimitInfo(out_cur_val.GetPointer(), out_lim_val.GetPointer(), group, resource);
}

View File

@@ -16,90 +16,24 @@
#pragma once
#include <stratosphere.hpp>
namespace ams::pm::dmnt {
namespace ams::pm {
class DebugMonitorServiceBase : public sf::IServiceObject {
protected:
class DebugMonitorService final {
public:
/* Actual command implementations. */
virtual Result GetModuleIdList(sf::Out<u32> out_count, const sf::OutBuffer &out_buf, u64 unused);
virtual Result GetExceptionProcessIdList(sf::Out<u32> out_count, const sf::OutArray<os::ProcessId> &out_process_ids);
virtual Result StartProcess(os::ProcessId process_id);
virtual Result GetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
virtual Result HookToCreateProcess(sf::OutCopyHandle out_hook, ncm::ProgramId program_id);
virtual Result GetApplicationProcessId(sf::Out<os::ProcessId> out);
virtual Result HookToCreateApplicationProcess(sf::OutCopyHandle out_hook);
virtual Result ClearHook(u32 which);
Result GetModuleIdList(sf::Out<u32> out_count, const sf::OutBuffer &out_buf, u64 unused);
Result GetExceptionProcessIdList(sf::Out<u32> out_count, const sf::OutArray<os::ProcessId> &out_process_ids);
Result StartProcess(os::ProcessId process_id);
Result GetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
Result HookToCreateProcess(sf::OutCopyHandle out_hook, ncm::ProgramId program_id);
Result GetApplicationProcessId(sf::Out<os::ProcessId> out);
Result HookToCreateApplicationProcess(sf::OutCopyHandle out_hook);
Result ClearHook(u32 which);
/* Atmosphere extension commands. */
virtual Result AtmosphereGetProcessInfo(sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
virtual Result AtmosphereGetCurrentLimitInfo(sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource);
};
/* This represents modern DebugMonitorService (5.0.0+). */
class DebugMonitorService final : public DebugMonitorServiceBase {
private:
enum class CommandId {
GetExceptionProcessIdList = 0,
StartProcess = 1,
GetProcessId = 2,
HookToCreateProcess = 3,
GetApplicationProcessId = 4,
HookToCreateApplicationProcess = 5,
ClearHook = 6,
AtmosphereGetProcessInfo = 65000,
AtmosphereGetCurrentLimitInfo = 65001,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 5.0.0-* */
MAKE_SERVICE_COMMAND_META(GetExceptionProcessIdList),
MAKE_SERVICE_COMMAND_META(StartProcess),
MAKE_SERVICE_COMMAND_META(GetProcessId),
MAKE_SERVICE_COMMAND_META(HookToCreateProcess),
MAKE_SERVICE_COMMAND_META(GetApplicationProcessId),
MAKE_SERVICE_COMMAND_META(HookToCreateApplicationProcess),
/* 6.0.0-* */
MAKE_SERVICE_COMMAND_META(ClearHook, hos::Version_6_0_0),
/* Atmosphere extensions. */
MAKE_SERVICE_COMMAND_META(AtmosphereGetProcessInfo),
MAKE_SERVICE_COMMAND_META(AtmosphereGetCurrentLimitInfo),
};
};
/* This represents deprecated DebugMonitorService (1.0.0-4.1.0). */
class DebugMonitorServiceDeprecated final : public DebugMonitorServiceBase {
private:
enum class CommandId {
GetModuleIdList = 0,
GetExceptionProcessIdList = 1,
StartProcess = 2,
GetProcessId = 3,
HookToCreateProcess = 4,
GetApplicationProcessId = 5,
HookToCreateApplicationProcess = 6,
AtmosphereGetProcessInfo = 65000,
AtmosphereGetCurrentLimitInfo = 65001,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0-4.1.0 */
MAKE_SERVICE_COMMAND_META(GetModuleIdList),
MAKE_SERVICE_COMMAND_META(GetExceptionProcessIdList),
MAKE_SERVICE_COMMAND_META(StartProcess),
MAKE_SERVICE_COMMAND_META(GetProcessId),
MAKE_SERVICE_COMMAND_META(HookToCreateProcess),
MAKE_SERVICE_COMMAND_META(GetApplicationProcessId),
MAKE_SERVICE_COMMAND_META(HookToCreateApplicationProcess),
/* Atmosphere extensions. */
MAKE_SERVICE_COMMAND_META(AtmosphereGetProcessInfo),
MAKE_SERVICE_COMMAND_META(AtmosphereGetCurrentLimitInfo),
};
Result AtmosphereGetProcessInfo(sf::OutCopyHandle out_process_handle, sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
Result AtmosphereGetCurrentLimitInfo(sf::Out<s64> out_cur_val, sf::Out<s64> out_lim_val, u32 group, u32 resource);
};
static_assert(pm::impl::IsIDebugMonitorInterface<DebugMonitorService>);
}

View File

@@ -17,11 +17,15 @@
#include "pm_info_service.hpp"
#include "impl/pm_process_manager.hpp"
namespace ams::pm::info {
namespace ams::pm {
/* Overrides for libstratosphere pm::info commands. */
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
return ldr::pm::HasLaunchedProgram(out, program_id);
namespace info {
Result HasLaunchedProgram(bool *out, ncm::ProgramId program_id) {
return ldr::pm::HasLaunchedProgram(out, program_id);
}
}
/* Actual command implementations. */

View File

@@ -16,18 +16,10 @@
#pragma once
#include <stratosphere.hpp>
namespace ams::pm::info {
namespace ams::pm {
class InformationService final : public sf::IServiceObject {
private:
enum class CommandId {
GetProgramId = 0,
AtmosphereGetProcessId = 65000,
AtmosphereHasLaunchedProgram = 65001,
AtmosphereGetProcessInfo = 65002,
};
private:
class InformationService final {
public:
/* Actual command implementations. */
Result GetProgramId(sf::Out<ncm::ProgramId> out, os::ProcessId process_id);
@@ -35,14 +27,7 @@ namespace ams::pm::info {
Result AtmosphereGetProcessId(sf::Out<os::ProcessId> out, ncm::ProgramId program_id);
Result AtmosphereHasLaunchedProgram(sf::Out<bool> out, ncm::ProgramId program_id);
Result AtmosphereGetProcessInfo(sf::Out<ncm::ProgramLocation> out_loc, sf::Out<cfg::OverrideStatus> out_status, os::ProcessId process_id);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetProgramId),
MAKE_SERVICE_COMMAND_META(AtmosphereGetProcessId),
MAKE_SERVICE_COMMAND_META(AtmosphereHasLaunchedProgram),
MAKE_SERVICE_COMMAND_META(AtmosphereGetProcessInfo),
};
};
static_assert(pm::impl::IsIInformationInterface<InformationService>);
}

View File

@@ -196,14 +196,14 @@ int main(int argc, char **argv)
/* NOTE: Extra sessions have been added to pm:bm and pm:info to facilitate access by the rest of stratosphere. */
/* Also Note: PM was rewritten in 5.0.0, so the shell and dmnt services are different before/after. */
if (hos::GetVersion() >= hos::Version_5_0_0) {
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::shell::ShellService>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::dmnt::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IShellInterface, pm::ShellService>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IDebugMonitorInterface, pm::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
} else {
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::shell::ShellServiceDeprecated>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::dmnt::DebugMonitorServiceDeprecated>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IDeprecatedShellInterface, pm::ShellService>(ShellServiceName, ShellMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IDeprecatedDebugMonitorInterface, pm::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
}
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::bm::BootModeService>(BootModeServiceName, BootModeMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::info::InformationService>(InformationServiceName, InformationMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IBootModeInterface, pm::BootModeService>(BootModeServiceName, BootModeMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<pm::impl::IInformationInterface, pm::InformationService>(InformationServiceName, InformationMaxSessions)));
/* Loop forever, servicing our services. */
g_server_manager.LoopProcess();

View File

@@ -17,59 +17,63 @@
#include "pm_shell_service.hpp"
#include "impl/pm_process_manager.hpp"
namespace ams::pm::shell {
namespace ams::pm {
/* Overrides for libstratosphere pm::shell commands. */
Result LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 launch_flags) {
return impl::LaunchProgram(out_process_id, loc, launch_flags);
namespace shell {
Result LaunchProgram(os::ProcessId *out_process_id, const ncm::ProgramLocation &loc, u32 launch_flags) {
return impl::LaunchProgram(out_process_id, loc, launch_flags);
}
}
/* Service command implementations. */
Result ShellServiceBase::LaunchProgram(sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags) {
Result ShellService::LaunchProgram(sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags) {
return pm::shell::LaunchProgram(out_process_id.GetPointer(), loc, flags);
}
Result ShellServiceBase::TerminateProcess(os::ProcessId process_id) {
Result ShellService::TerminateProcess(os::ProcessId process_id) {
return impl::TerminateProcess(process_id);
}
Result ShellServiceBase::TerminateProgram(ncm::ProgramId program_id) {
Result ShellService::TerminateProgram(ncm::ProgramId program_id) {
return impl::TerminateProgram(program_id);
}
void ShellServiceBase::GetProcessEventHandle(sf::OutCopyHandle out) {
void ShellService::GetProcessEventHandle(sf::OutCopyHandle out) {
R_ABORT_UNLESS(impl::GetProcessEventHandle(out.GetHandlePointer()));
}
void ShellServiceBase::GetProcessEventInfo(sf::Out<ProcessEventInfo> out) {
void ShellService::GetProcessEventInfo(sf::Out<ProcessEventInfo> out) {
R_ABORT_UNLESS(impl::GetProcessEventInfo(out.GetPointer()));
}
Result ShellServiceBase::CleanupProcess(os::ProcessId process_id) {
Result ShellService::CleanupProcess(os::ProcessId process_id) {
return impl::CleanupProcess(process_id);
}
Result ShellServiceBase::ClearExceptionOccurred(os::ProcessId process_id) {
Result ShellService::ClearExceptionOccurred(os::ProcessId process_id) {
return impl::ClearExceptionOccurred(process_id);
}
void ShellServiceBase::NotifyBootFinished() {
void ShellService::NotifyBootFinished() {
R_ABORT_UNLESS(impl::NotifyBootFinished());
}
Result ShellServiceBase::GetApplicationProcessIdForShell(sf::Out<os::ProcessId> out) {
Result ShellService::GetApplicationProcessIdForShell(sf::Out<os::ProcessId> out) {
return impl::GetApplicationProcessId(out.GetPointer());
}
Result ShellServiceBase::BoostSystemMemoryResourceLimit(u64 boost_size) {
Result ShellService::BoostSystemMemoryResourceLimit(u64 boost_size) {
return impl::BoostSystemMemoryResourceLimit(boost_size);
}
Result ShellServiceBase::BoostApplicationThreadResourceLimit() {
Result ShellService::BoostApplicationThreadResourceLimit() {
return impl::BoostApplicationThreadResourceLimit();
}
void ShellServiceBase::GetBootFinishedEventHandle(sf::OutCopyHandle out) {
void ShellService::GetBootFinishedEventHandle(sf::OutCopyHandle out) {
R_ABORT_UNLESS(impl::GetBootFinishedEventHandle(out.GetHandlePointer()));
}

View File

@@ -16,91 +16,24 @@
#pragma once
#include <stratosphere.hpp>
namespace ams::pm::shell {
namespace ams::pm {
class ShellServiceBase : public sf::IServiceObject {
protected:
class ShellService final {
public:
/* Actual command implementations. */
virtual Result LaunchProgram(sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags);
virtual Result TerminateProcess(os::ProcessId process_id);
virtual Result TerminateProgram(ncm::ProgramId program_id);
virtual void GetProcessEventHandle(sf::OutCopyHandle out);
virtual void GetProcessEventInfo(sf::Out<ProcessEventInfo> out);
virtual Result CleanupProcess(os::ProcessId process_id);
virtual Result ClearExceptionOccurred(os::ProcessId process_id);
virtual void NotifyBootFinished();
virtual Result GetApplicationProcessIdForShell(sf::Out<os::ProcessId> out);
virtual Result BoostSystemMemoryResourceLimit(u64 boost_size);
virtual Result BoostApplicationThreadResourceLimit();
virtual void GetBootFinishedEventHandle(sf::OutCopyHandle out);
};
/* This represents modern ShellService (5.0.0+). */
class ShellService final : public ShellServiceBase {
private:
enum class CommandId {
LaunchProgram = 0,
TerminateProcess = 1,
TerminateProgram = 2,
GetProcessEventHandle = 3,
GetProcessEventInfo = 4,
NotifyBootFinished = 5,
GetApplicationProcessIdForShell = 6,
BoostSystemMemoryResourceLimit = 7,
BoostApplicationThreadResourceLimit = 8,
GetBootFinishedEventHandle = 9,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 5.0.0-* */
MAKE_SERVICE_COMMAND_META(LaunchProgram),
MAKE_SERVICE_COMMAND_META(TerminateProcess),
MAKE_SERVICE_COMMAND_META(TerminateProgram),
MAKE_SERVICE_COMMAND_META(GetProcessEventHandle),
MAKE_SERVICE_COMMAND_META(GetProcessEventInfo),
MAKE_SERVICE_COMMAND_META(NotifyBootFinished),
MAKE_SERVICE_COMMAND_META(GetApplicationProcessIdForShell),
MAKE_SERVICE_COMMAND_META(BoostSystemMemoryResourceLimit),
/* 7.0.0-* */
MAKE_SERVICE_COMMAND_META(BoostApplicationThreadResourceLimit, hos::Version_7_0_0),
/* 8.0.0-* */
MAKE_SERVICE_COMMAND_META(GetBootFinishedEventHandle, hos::Version_8_0_0),
};
};
/* This represents deprecated ShellService (1.0.0-4.1.0). */
class ShellServiceDeprecated final : public ShellServiceBase {
private:
enum class CommandId {
LaunchProgram = 0,
TerminateProcess = 1,
TerminateProgram = 2,
GetProcessEventHandle = 3,
GetProcessEventInfo = 4,
CleanupProcess = 5,
ClearExceptionOccurred = 6,
NotifyBootFinished = 7,
GetApplicationProcessIdForShell = 8,
BoostSystemMemoryResourceLimit = 9,
};
public:
DEFINE_SERVICE_DISPATCH_TABLE {
/* 1.0.0-4.1.0 */
MAKE_SERVICE_COMMAND_META(LaunchProgram),
MAKE_SERVICE_COMMAND_META(TerminateProcess),
MAKE_SERVICE_COMMAND_META(TerminateProgram),
MAKE_SERVICE_COMMAND_META(GetProcessEventHandle),
MAKE_SERVICE_COMMAND_META(GetProcessEventInfo),
MAKE_SERVICE_COMMAND_META(CleanupProcess),
MAKE_SERVICE_COMMAND_META(ClearExceptionOccurred),
MAKE_SERVICE_COMMAND_META(NotifyBootFinished),
MAKE_SERVICE_COMMAND_META(GetApplicationProcessIdForShell),
/* 4.0.0-4.1.0 */
MAKE_SERVICE_COMMAND_META(BoostSystemMemoryResourceLimit, hos::Version_4_0_0),
};
Result LaunchProgram(sf::Out<os::ProcessId> out_process_id, const ncm::ProgramLocation &loc, u32 flags);
Result TerminateProcess(os::ProcessId process_id);
Result TerminateProgram(ncm::ProgramId program_id);
void GetProcessEventHandle(sf::OutCopyHandle out);
void GetProcessEventInfo(sf::Out<ProcessEventInfo> out);
Result CleanupProcess(os::ProcessId process_id);
Result ClearExceptionOccurred(os::ProcessId process_id);
void NotifyBootFinished();
Result GetApplicationProcessIdForShell(sf::Out<os::ProcessId> out);
Result BoostSystemMemoryResourceLimit(u64 boost_size);
Result BoostApplicationThreadResourceLimit();
void GetBootFinishedEventHandle(sf::OutCopyHandle out);
};
static_assert(pm::impl::IsIShellInterface<ShellService>);
}

View File

@@ -413,7 +413,7 @@ namespace ams::ro::impl {
}
/* Service implementations. */
Result LoadNrr(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, ModuleType expected_type, bool enforce_type) {
Result RegisterModuleInfo(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, ModuleType expected_type, bool enforce_type) {
/* Get context. */
ProcessContext *context = GetContextById(context_id);
AMS_ABORT_UNLESS(context != nullptr);
@@ -454,7 +454,7 @@ namespace ams::ro::impl {
return ResultSuccess();
}
Result UnloadNrr(size_t context_id, u64 nrr_address) {
Result UnregisterModuleInfo(size_t context_id, u64 nrr_address) {
/* Get context. */
ProcessContext *context = GetContextById(context_id);
AMS_ABORT_UNLESS(context != nullptr);
@@ -476,7 +476,7 @@ namespace ams::ro::impl {
return UnmapNrr(context->process_handle, nrr_backup.mapped_header, nrr_backup.nrr_heap_address, nrr_backup.nrr_heap_size, nrr_backup.mapped_code_address);
}
Result LoadNro(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
Result MapManualLoadModuleMemory(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
/* Get context. */
ProcessContext *context = GetContextById(context_id);
AMS_ABORT_UNLESS(context != nullptr);
@@ -522,7 +522,7 @@ namespace ams::ro::impl {
return ResultSuccess();
}
Result UnloadNro(size_t context_id, u64 nro_address) {
Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address) {
/* Get context. */
ProcessContext *context = GetContextById(context_id);
AMS_ABORT_UNLESS(context != nullptr);

View File

@@ -35,10 +35,10 @@ namespace ams::ro::impl {
void UnregisterProcess(size_t context_id);
/* Service implementations. */
Result LoadNrr(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, ModuleType expected_type, bool enforce_type);
Result UnloadNrr(size_t context_id, u64 nrr_address);
Result LoadNro(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
Result UnloadNro(size_t context_id, u64 nro_address);
Result RegisterModuleInfo(size_t context_id, Handle process_h, u64 nrr_address, u64 nrr_size, ModuleType expected_type, bool enforce_type);
Result UnregisterModuleInfo(size_t context_id, u64 nrr_address);
Result MapManualLoadModuleMemory(u64 *out_address, size_t context_id, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
Result UnmapManualLoadModuleMemory(size_t context_id, u64 nro_address);
/* Debug service implementations. */
Result GetProcessModuleInfo(u32 *out_count, LoaderModuleInfo *out_infos, size_t max_out_count, os::ProcessId process_id);

View File

@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "ro_debug_monitor.hpp"
#include "ro_debug_monitor_service.hpp"
#include "impl/ro_service_impl.hpp"
namespace ams::ro {

View File

@@ -18,18 +18,10 @@
namespace ams::ro {
class DebugMonitorService final : public sf::IServiceObject {
protected:
enum class CommandId {
GetProcessModuleInfo = 0,
};
private:
/* Actual commands. */
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
class DebugMonitorService final {
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetProcessModuleInfo),
};
Result GetProcessModuleInfo(sf::Out<u32> out_count, const sf::OutArray<LoaderModuleInfo> &out_infos, os::ProcessId process_id);
};
static_assert(ro::impl::IsIDebugMonitorInterface<DebugMonitorService>);
}

View File

@@ -14,8 +14,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "ro_debug_monitor.hpp"
#include "ro_service.hpp"
#include "ro_debug_monitor_service.hpp"
#include "ro_ro_service.hpp"
extern "C" {
extern u32 __start__;
@@ -84,10 +84,6 @@ void __appExit(void) {
setsysExit();
}
/* Helpers to create RO objects. */
static constexpr auto MakeRoServiceForSelf = []() { return std::make_shared<ro::Service>(ro::ModuleType::ForSelf); };
static constexpr auto MakeRoServiceForOthers = []() { return std::make_shared<ro::Service>(ro::ModuleType::ForOthers); };
namespace {
/* ldr:ro, ro:dmnt, ro:1. */
@@ -122,11 +118,11 @@ int main(int argc, char **argv)
}
/* Create services. */
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IDebugMonitorInterface, ro::DebugMonitorService>(DebugMonitorServiceName, DebugMonitorMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::Service, +MakeRoServiceForSelf>(ForSelfServiceName, ForSelfMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoServiceForSelf>(ForSelfServiceName, ForSelfMaxSessions)));
if (hos::GetVersion() >= hos::Version_7_0_0) {
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::Service, +MakeRoServiceForOthers>(ForOthersServiceName, ForOthersMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<ro::impl::IRoInterface, ro::RoServiceForOthers>(ForOthersServiceName, ForOthersMaxSessions)));
}
/* Loop forever, servicing our services. */

View File

@@ -0,0 +1,67 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
#include "ro_ro_service.hpp"
#include "impl/ro_service_impl.hpp"
namespace ams::ro {
void SetDevelopmentHardware(bool is_development_hardware) {
impl::SetDevelopmentHardware(is_development_hardware);
}
void SetDevelopmentFunctionEnabled(bool is_development_function_enabled) {
impl::SetDevelopmentFunctionEnabled(is_development_function_enabled);
}
RoService::RoService(ModuleType t) : context_id(impl::InvalidContextId), type(t) {
/* ... */
}
RoService::~RoService() {
impl::UnregisterProcess(this->context_id);
}
Result RoService::MapManualLoadModuleMemory(sf::Out<u64> load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::MapManualLoadModuleMemory(load_address.GetPointer(), this->context_id, nro_address, nro_size, bss_address, bss_size);
}
Result RoService::UnmapManualLoadModuleMemory(const sf::ClientProcessId &client_pid, u64 nro_address) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::UnmapManualLoadModuleMemory(this->context_id, nro_address);
}
Result RoService::RegisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::RegisterModuleInfo(this->context_id, svc::InvalidHandle, nrr_address, nrr_size, ModuleType::ForSelf, true);
}
Result RoService::UnregisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::UnregisterModuleInfo(this->context_id, nrr_address);
}
Result RoService::RegisterProcessHandle(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h) {
return impl::RegisterProcess(std::addressof(this->context_id), process_h.GetValue(), client_pid.GetValue());
}
Result RoService::RegisterModuleInfoEx(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::RegisterModuleInfo(this->context_id, process_h.GetValue(), nrr_address, nrr_size, this->type, this->type == ModuleType::ForOthers);
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
namespace ams::ro {
/* Access utilities. */
void SetDevelopmentHardware(bool is_development_hardware);
void SetDevelopmentFunctionEnabled(bool is_development_function_enabled);
class RoService {
private:
size_t context_id;
ModuleType type;
protected:
explicit RoService(ModuleType t);
public:
virtual ~RoService();
public:
/* Actual commands. */
Result MapManualLoadModuleMemory(sf::Out<u64> out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
Result UnmapManualLoadModuleMemory(const sf::ClientProcessId &client_pid, u64 nro_address);
Result RegisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size);
Result UnregisterModuleInfo(const sf::ClientProcessId &client_pid, u64 nrr_address);
Result RegisterProcessHandle(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h);
Result RegisterModuleInfoEx(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h);
};
static_assert(ro::impl::IsIRoInterface<RoService>);
class RoServiceForSelf final : public RoService {
public:
RoServiceForSelf() : RoService(ro::ModuleType::ForSelf) { /* ... */ }
};
/* TODO: This is really JitPlugin... */
class RoServiceForOthers final : public RoService {
public:
RoServiceForOthers() : RoService(ro::ModuleType::ForOthers) { /* ... */ }
};
}

View File

@@ -1,67 +0,0 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
#include "ro_service.hpp"
#include "impl/ro_service_impl.hpp"
namespace ams::ro {
void SetDevelopmentHardware(bool is_development_hardware) {
impl::SetDevelopmentHardware(is_development_hardware);
}
void SetDevelopmentFunctionEnabled(bool is_development_function_enabled) {
impl::SetDevelopmentFunctionEnabled(is_development_function_enabled);
}
Service::Service(ModuleType t) : context_id(impl::InvalidContextId), type(t) {
/* ... */
}
Service::~Service() {
impl::UnregisterProcess(this->context_id);
}
Result Service::LoadNro(sf::Out<u64> load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::LoadNro(load_address.GetPointer(), this->context_id, nro_address, nro_size, bss_address, bss_size);
}
Result Service::UnloadNro(const sf::ClientProcessId &client_pid, u64 nro_address) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::UnloadNro(this->context_id, nro_address);
}
Result Service::LoadNrr(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::LoadNrr(this->context_id, INVALID_HANDLE, nrr_address, nrr_size, ModuleType::ForSelf, true);
}
Result Service::UnloadNrr(const sf::ClientProcessId &client_pid, u64 nrr_address) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::UnloadNrr(this->context_id, nrr_address);
}
Result Service::Initialize(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h) {
return impl::RegisterProcess(&this->context_id, process_h.GetValue(), client_pid.GetValue());
}
Result Service::LoadNrrEx(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h) {
R_TRY(impl::ValidateProcess(this->context_id, client_pid.GetValue()));
return impl::LoadNrr(this->context_id, process_h.GetValue(), nrr_address, nrr_size, this->type, this->type == ModuleType::ForOthers);
}
}

View File

@@ -1,62 +0,0 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
namespace ams::ro {
/* Access utilities. */
void SetDevelopmentHardware(bool is_development_hardware);
void SetDevelopmentFunctionEnabled(bool is_development_function_enabled);
class Service final : public sf::IServiceObject {
protected:
enum class CommandId {
LoadNro = 0,
UnloadNro = 1,
LoadNrr = 2,
UnloadNrr = 3,
Initialize = 4,
LoadNrrEx = 10,
};
private:
size_t context_id;
ModuleType type;
public:
explicit Service(ModuleType t);
virtual ~Service();
private:
/* Actual commands. */
Result LoadNro(sf::Out<u64> out_load_address, const sf::ClientProcessId &client_pid, u64 nro_address, u64 nro_size, u64 bss_address, u64 bss_size);
Result UnloadNro(const sf::ClientProcessId &client_pid, u64 nro_address);
Result LoadNrr(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size);
Result UnloadNrr(const sf::ClientProcessId &client_pid, u64 nrr_address);
Result Initialize(const sf::ClientProcessId &client_pid, sf::CopyHandle process_h);
Result LoadNrrEx(const sf::ClientProcessId &client_pid, u64 nrr_address, u64 nrr_size, sf::CopyHandle process_h);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(LoadNro),
MAKE_SERVICE_COMMAND_META(UnloadNro),
MAKE_SERVICE_COMMAND_META(LoadNrr),
MAKE_SERVICE_COMMAND_META(UnloadNrr),
MAKE_SERVICE_COMMAND_META(Initialize),
MAKE_SERVICE_COMMAND_META(LoadNrrEx, hos::Version_7_0_0),
};
};
}

View File

@@ -14,20 +14,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "sm_dmnt_service.hpp"
#include "sm_debug_monitor_service.hpp"
#include "impl/sm_service_manager.hpp"
namespace ams::sm {
Result DmntService::AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service) {
Result DebugMonitorService::AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service) {
return impl::GetServiceRecord(record.GetPointer(), service);
}
void DmntService::AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset) {
void DebugMonitorService::AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset) {
R_ABORT_UNLESS(impl::ListServiceRecords(records.GetPointer(), out_count.GetPointer(), offset, records.GetSize()));
}
void DmntService::AtmosphereGetRecordSize(sf::Out<u64> record_size) {
void DebugMonitorService::AtmosphereGetRecordSize(sf::Out<u64> record_size) {
record_size.SetValue(sizeof(ServiceRecord));
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
namespace ams::sm {
/* Service definition. */
class DebugMonitorService final {
public:
Result AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service);
void AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset);
void AtmosphereGetRecordSize(sf::Out<u64> record_size);
};
static_assert(sm::impl::IsIDebugMonitorInterface<DebugMonitorService>);
}

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
namespace ams::sm {
/* Service definition. */
class DmntService final : public sf::IServiceObject {
protected:
/* Command IDs. */
enum class CommandId {
AtmosphereGetRecord = 65000,
AtmosphereListRecords = 65001,
AtmosphereGetRecordSize = 65002,
};
private:
/* Actual commands. */
virtual Result AtmosphereGetRecord(sf::Out<ServiceRecord> record, ServiceName service);
virtual void AtmosphereListRecords(const sf::OutArray<ServiceRecord> &records, sf::Out<u64> out_count, u64 offset);
virtual void AtmosphereGetRecordSize(sf::Out<u64> record_size);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(AtmosphereGetRecord),
MAKE_SERVICE_COMMAND_META(AtmosphereListRecords),
MAKE_SERVICE_COMMAND_META(AtmosphereGetRecordSize),
};
};
}

View File

@@ -16,7 +16,7 @@
#include <stratosphere.hpp>
#include "sm_user_service.hpp"
#include "sm_manager_service.hpp"
#include "sm_dmnt_service.hpp"
#include "sm_debug_monitor_service.hpp"
#include "impl/sm_service_manager.hpp"
extern "C" {
@@ -101,14 +101,14 @@ int main(int argc, char **argv)
{
Handle sm_h;
R_ABORT_UNLESS(svcManageNamedPort(&sm_h, "sm:", 0x40));
g_server_manager.RegisterServer<sm::UserService>(sm_h);
g_server_manager.RegisterServer<sm::impl::IUserInterface, sm::UserService>(sm_h);
}
/* Create sm:m manually. */
{
Handle smm_h;
R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smm_h, sm::ServiceName::Encode("sm:m"), 1));
g_server_manager.RegisterServer<sm::ManagerService>(smm_h);
g_server_manager.RegisterServer<sm::impl::IManagerInterface, sm::ManagerService>(smm_h);
}
/*===== ATMOSPHERE EXTENSION =====*/
@@ -116,7 +116,7 @@ int main(int argc, char **argv)
{
Handle smdmnt_h;
R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smdmnt_h, sm::ServiceName::Encode("sm:dmnt"), 1));
g_server_manager.RegisterServer<sm::DmntService>(smdmnt_h);
g_server_manager.RegisterServer<sm::impl::IDebugMonitorInterface, sm::DebugMonitorService>(smdmnt_h);
}
/*================================*/

View File

@@ -19,33 +19,14 @@
namespace ams::sm {
/* Service definition. */
class ManagerService final : public sf::IServiceObject {
protected:
/* Command IDs. */
enum class CommandId {
RegisterProcess = 0,
UnregisterProcess = 1,
AtmosphereEndInitDefers = 65000,
AtmosphereHasMitm = 65001,
AtmosphereRegisterProcess = 65002,
};
private:
/* Actual commands. */
virtual Result RegisterProcess(os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
virtual Result UnregisterProcess(os::ProcessId process_id);
virtual void AtmosphereEndInitDefers();
virtual void AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereRegisterProcess(os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus override_status, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
class ManagerService final {
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(RegisterProcess),
MAKE_SERVICE_COMMAND_META(UnregisterProcess),
MAKE_SERVICE_COMMAND_META(AtmosphereEndInitDefers),
MAKE_SERVICE_COMMAND_META(AtmosphereHasMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereRegisterProcess),
};
Result RegisterProcess(os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
Result UnregisterProcess(os::ProcessId process_id);
void AtmosphereEndInitDefers();
void AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
Result AtmosphereRegisterProcess(os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus override_status, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac);
};
static_assert(sm::impl::IsIManagerInterface<ManagerService>);
}

View File

@@ -19,20 +19,18 @@
namespace ams::sm {
Result UserService::Initialize(const sf::ClientProcessId &client_process_id) {
Result UserService::RegisterClient(const sf::ClientProcessId &client_process_id) {
this->process_id = client_process_id.GetValue();
this->has_initialized = true;
return ResultSuccess();
}
Result UserService::EnsureInitialized() {
if (!this->has_initialized) {
return sm::ResultInvalidClient();
}
R_UNLESS(this->has_initialized, sm::ResultInvalidClient());
return ResultSuccess();
}
Result UserService::GetService(sf::OutMoveHandle out_h, ServiceName service) {
Result UserService::GetServiceHandle(sf::OutMoveHandle out_h, ServiceName service) {
R_TRY(this->EnsureInitialized());
return impl::GetServiceHandle(out_h.GetHandlePointer(), this->process_id, service);
}

View File

@@ -20,26 +20,7 @@
namespace ams::sm {
/* Service definition. */
class UserService final : public sf::IServiceObject {
protected:
/* Command IDs. */
enum class CommandId {
Initialize = 0,
GetService = 1,
RegisterService = 2,
UnregisterService = 3,
AtmosphereInstallMitm = 65000,
AtmosphereUninstallMitm = 65001,
/* Deprecated: AtmosphereAssociatePidTidForMitm = 65002 */
AtmosphereAcknowledgeMitmSession = 65003,
AtmosphereHasMitm = 65004,
AtmosphereWaitMitm = 65005,
AtmosphereDeclareFutureMitm = 65006,
AtmosphereHasService = 65100,
AtmosphereWaitService = 65101,
};
class UserService final {
private:
os::ProcessId process_id = os::InvalidProcessId;
bool has_initialized = false;
@@ -47,38 +28,22 @@ namespace ams::sm {
Result EnsureInitialized();
public:
/* Official commands. */
virtual Result Initialize(const sf::ClientProcessId &client_process_id);
virtual Result GetService(sf::OutMoveHandle out_h, ServiceName service);
virtual Result RegisterService(sf::OutMoveHandle out_h, ServiceName service, u32 max_sessions, bool is_light);
virtual Result UnregisterService(ServiceName service);
Result RegisterClient(const sf::ClientProcessId &client_process_id);
Result GetServiceHandle(sf::OutMoveHandle out_h, ServiceName service);
Result RegisterService(sf::OutMoveHandle out_h, ServiceName service, u32 max_sessions, bool is_light);
Result UnregisterService(ServiceName service);
/* Atmosphere commands. */
virtual Result AtmosphereInstallMitm(sf::OutMoveHandle srv_h, sf::OutMoveHandle qry_h, ServiceName service);
virtual Result AtmosphereUninstallMitm(ServiceName service);
virtual Result AtmosphereAcknowledgeMitmSession(sf::Out<MitmProcessInfo> client_info, sf::OutMoveHandle fwd_h, ServiceName service);
virtual Result AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitMitm(ServiceName service);
virtual Result AtmosphereDeclareFutureMitm(ServiceName service);
Result AtmosphereInstallMitm(sf::OutMoveHandle srv_h, sf::OutMoveHandle qry_h, ServiceName service);
Result AtmosphereUninstallMitm(ServiceName service);
Result AtmosphereAcknowledgeMitmSession(sf::Out<MitmProcessInfo> client_info, sf::OutMoveHandle fwd_h, ServiceName service);
Result AtmosphereHasMitm(sf::Out<bool> out, ServiceName service);
Result AtmosphereWaitMitm(ServiceName service);
Result AtmosphereDeclareFutureMitm(ServiceName service);
virtual Result AtmosphereHasService(sf::Out<bool> out, ServiceName service);
virtual Result AtmosphereWaitService(ServiceName service);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(Initialize),
MAKE_SERVICE_COMMAND_META(GetService),
MAKE_SERVICE_COMMAND_META(RegisterService),
MAKE_SERVICE_COMMAND_META(UnregisterService),
MAKE_SERVICE_COMMAND_META(AtmosphereInstallMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereUninstallMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereAcknowledgeMitmSession),
MAKE_SERVICE_COMMAND_META(AtmosphereHasMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereWaitMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereDeclareFutureMitm),
MAKE_SERVICE_COMMAND_META(AtmosphereHasService),
MAKE_SERVICE_COMMAND_META(AtmosphereWaitService),
};
Result AtmosphereHasService(sf::Out<bool> out, ServiceName service);
Result AtmosphereWaitService(ServiceName service);
};
static_assert(sm::impl::IsIUserInterface<UserService>);
}

View File

@@ -24,39 +24,39 @@ namespace ams::spl::impl {
/* Convenient defines. */
constexpr size_t DeviceAddressSpaceAlign = 0x400000;
constexpr u32 WorkBufferMapBase = 0x80000000u;
constexpr u32 CryptAesInMapBase = 0x90000000u;
constexpr u32 CryptAesOutMapBase = 0xC0000000u;
constexpr size_t CryptAesSizeMax = static_cast<size_t>(CryptAesOutMapBase - CryptAesInMapBase);
constexpr u32 WorkBufferMapBase = 0x80000000u;
constexpr u32 ComputeAesInMapBase = 0x90000000u;
constexpr u32 ComputeAesOutMapBase = 0xC0000000u;
constexpr size_t ComputeAesSizeMax = static_cast<size_t>(ComputeAesOutMapBase - ComputeAesInMapBase);
constexpr size_t RsaPrivateKeySize = 0x100;
constexpr size_t RsaPrivateKeyMetaSize = 0x30;
constexpr size_t DeviceUniqueDataMetaSize = 0x30;
constexpr size_t LabelDigestSizeMax = 0x20;
constexpr size_t WorkBufferSizeMax = 0x800;
constexpr s32 MaxPhysicalAesKeyslots = 6;
constexpr s32 MaxPhysicalAesKeyslotsDeprecated = 4;
constexpr s32 MaxPhysicalAesKeySlots = 6;
constexpr s32 MaxPhysicalAesKeySlotsDeprecated = 4;
constexpr s32 MaxVirtualAesKeyslots = 9;
constexpr s32 MaxVirtualAesKeySlots = 9;
/* Keyslot management. */
/* KeySlot management. */
KeySlotCache g_keyslot_cache;
std::optional<KeySlotCacheEntry> g_keyslot_cache_entry[MaxPhysicalAesKeyslots];
std::optional<KeySlotCacheEntry> g_keyslot_cache_entry[MaxPhysicalAesKeySlots];
inline s32 GetMaxPhysicalKeyslots() {
return (hos::GetVersion() >= hos::Version_6_0_0) ? MaxPhysicalAesKeyslots : MaxPhysicalAesKeyslotsDeprecated;
inline s32 GetMaxPhysicalKeySlots() {
return (hos::GetVersion() >= hos::Version_6_0_0) ? MaxPhysicalAesKeySlots : MaxPhysicalAesKeySlotsDeprecated;
}
constexpr s32 VirtualKeySlotMin = 16;
constexpr s32 VirtualKeySlotMax = VirtualKeySlotMin + MaxVirtualAesKeyslots - 1;
constexpr s32 VirtualKeySlotMax = VirtualKeySlotMin + MaxVirtualAesKeySlots - 1;
constexpr inline bool IsVirtualKeySlot(s32 keyslot) {
return VirtualKeySlotMin <= keyslot && keyslot <= VirtualKeySlotMax;
}
inline bool IsPhysicalKeySlot(s32 keyslot) {
return keyslot < GetMaxPhysicalKeyslots();
return keyslot < GetMaxPhysicalKeySlots();
}
constexpr inline s32 GetVirtualKeySlotIndex(s32 keyslot) {
@@ -71,16 +71,16 @@ namespace ams::spl::impl {
}
void InitializeKeySlotCache() {
for (s32 i = 0; i < MaxPhysicalAesKeyslots; i++) {
for (s32 i = 0; i < MaxPhysicalAesKeySlots; i++) {
g_keyslot_cache_entry[i].emplace(i);
g_keyslot_cache.AddEntry(std::addressof(g_keyslot_cache_entry[i].value()));
}
}
enum class KeySlotContentType {
None = 0,
AesKey = 1,
TitleKey = 2,
None = 0,
AesKey = 1,
PreparedKey = 2,
};
struct KeySlotContents {
@@ -92,15 +92,15 @@ namespace ams::spl::impl {
} aes_key;
struct {
AccessKey access_key;
} title_key;
} prepared_key;
};
};
const void *g_keyslot_owners[MaxVirtualAesKeyslots];
KeySlotContents g_keyslot_contents[MaxVirtualAesKeyslots];
KeySlotContents g_physical_keyslot_contents_for_backwards_compatibility[MaxPhysicalAesKeyslots];
const void *g_keyslot_owners[MaxVirtualAesKeySlots];
KeySlotContents g_keyslot_contents[MaxVirtualAesKeySlots];
KeySlotContents g_physical_keyslot_contents_for_backwards_compatibility[MaxPhysicalAesKeySlots];
void ClearPhysicalKeyslot(s32 keyslot) {
void ClearPhysicalKeySlot(s32 keyslot) {
AMS_ASSERT(IsPhysicalKeySlot(keyslot));
AccessKey access_key = {};
@@ -139,13 +139,13 @@ namespace ams::spl::impl {
if (load) {
switch (contents->type) {
case KeySlotContentType::None:
ClearPhysicalKeyslot(phys_slot);
ClearPhysicalKeySlot(phys_slot);
break;
case KeySlotContentType::AesKey:
R_ABORT_UNLESS(smc::ConvertResult(smc::LoadAesKey(phys_slot, contents->aes_key.access_key, contents->aes_key.key_source)));
break;
case KeySlotContentType::TitleKey:
R_ABORT_UNLESS(smc::ConvertResult(smc::LoadTitleKey(phys_slot, contents->title_key.access_key)));
case KeySlotContentType::PreparedKey:
R_ABORT_UNLESS(smc::ConvertResult(smc::LoadPreparedAesKey(phys_slot, contents->prepared_key.access_key)));
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
@@ -169,32 +169,32 @@ namespace ams::spl::impl {
return ResultSuccess();
}
Result LoadVirtualTitleKey(s32 keyslot, const AccessKey &access_key) {
Result LoadVirtualPreparedAesKey(s32 keyslot, const AccessKey &access_key) {
/* Ensure we can load into the slot. */
const s32 phys_slot = GetPhysicalKeySlot(keyslot, false);
R_TRY(smc::ConvertResult(smc::LoadTitleKey(phys_slot, access_key)));
R_TRY(smc::ConvertResult(smc::LoadPreparedAesKey(phys_slot, access_key)));
/* Update our contents. */
const s32 index = GetVirtualKeySlotIndex(keyslot);
g_keyslot_contents[index].type = KeySlotContentType::TitleKey;
g_keyslot_contents[index].title_key.access_key = access_key;
g_keyslot_contents[index].type = KeySlotContentType::PreparedKey;
g_keyslot_contents[index].prepared_key.access_key = access_key;
return ResultSuccess();
}
/* Type definitions. */
class ScopedAesKeyslot {
class ScopedAesKeySlot {
private:
s32 slot;
bool has_slot;
public:
ScopedAesKeyslot() : slot(-1), has_slot(false) {
ScopedAesKeySlot() : slot(-1), has_slot(false) {
/* ... */
}
~ScopedAesKeyslot() {
~ScopedAesKeySlot() {
if (this->has_slot) {
FreeAesKeyslot(slot, this);
DeallocateAesKeySlot(slot, this);
}
}
@@ -203,7 +203,7 @@ namespace ams::spl::impl {
}
Result Allocate() {
R_TRY(AllocateAesKeyslot(&this->slot, this));
R_TRY(AllocateAesKeySlot(&this->slot, this));
this->has_slot = true;
return ResultSuccess();
}
@@ -269,7 +269,7 @@ namespace ams::spl::impl {
void InitializeSeEvents() {
u64 irq_num;
AMS_ABORT_UNLESS(smc::GetConfig(&irq_num, 1, SplConfigItem_SecurityEngineIrqNumber) == smc::Result::Success);
AMS_ABORT_UNLESS(smc::GetConfig(&irq_num, 1, ConfigItem::SecurityEngineInterruptNumber) == smc::Result::Success);
os::InitializeInterruptEvent(std::addressof(g_se_event), irq_num, os::EventClearMode_AutoClear);
R_ABORT_UNLESS(os::CreateSystemEvent(std::addressof(g_se_keyslot_available_event), os::EventClearMode_AutoClear, true));
@@ -320,7 +320,7 @@ namespace ams::spl::impl {
WaitSeOperationComplete();
smc::Result op_res;
smc::Result res = smc::CheckStatus(&op_res, op_key);
smc::Result res = smc::GetResult(&op_res, op_key);
if (res != smc::Result::Success) {
return res;
}
@@ -332,7 +332,7 @@ namespace ams::spl::impl {
WaitSeOperationComplete();
smc::Result op_res;
smc::Result res = smc::GetResult(&op_res, out_buf, out_buf_size, op_key);
smc::Result res = smc::GetResultData(&op_res, out_buf, out_buf_size, op_key);
if (res != smc::Result::Success) {
return res;
}
@@ -340,17 +340,17 @@ namespace ams::spl::impl {
return op_res;
}
/* Internal Keyslot utility. */
Result ValidateAesKeyslot(s32 keyslot, const void *owner) {
/* Internal KeySlot utility. */
Result ValidateAesKeySlot(s32 keyslot, const void *owner) {
/* Allow the use of physical keyslots on 1.0.0. */
if (hos::GetVersion() == hos::Version_1_0_0) {
R_SUCCEED_IF(IsPhysicalKeySlot(keyslot));
}
R_UNLESS(IsVirtualKeySlot(keyslot), spl::ResultInvalidKeyslot());
R_UNLESS(IsVirtualKeySlot(keyslot), spl::ResultInvalidKeySlot());
const s32 index = GetVirtualKeySlotIndex(keyslot);
R_UNLESS(g_keyslot_owners[index] == owner, spl::ResultInvalidKeyslot());
R_UNLESS(g_keyslot_owners[index] == owner, spl::ResultInvalidKeySlot());
return ResultSuccess();
}
@@ -377,11 +377,11 @@ namespace ams::spl::impl {
std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key;
const IvCtr iv_ctr = {};
const u32 mode = smc::GetCryptAesMode(smc::CipherMode::CbcDecrypt, GetPhysicalKeySlot(keyslot, true));
const u32 mode = smc::GetComputeAesMode(smc::CipherMode::CbcDecrypt, GetPhysicalKeySlot(keyslot, true));
const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.out);
const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(DecryptAesBlockLayout, crypt_ctx.in);
smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, sizeof(layout->in_block));
smc::Result res = smc::ComputeAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, sizeof(layout->in_block));
if (res != smc::Result::Success) {
return res;
}
@@ -397,33 +397,33 @@ namespace ams::spl::impl {
}
/* Implementation wrappers for API commands. */
Result ImportSecureExpModKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
struct ImportSecureExpModKeyLayout {
u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
Result DecryptAndStoreDeviceUniqueKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
struct DecryptAndStoreDeviceUniqueKeyLayout {
u8 data[DeviceUniqueDataMetaSize + 2 * RsaPrivateKeySize + 0x10];
};
ImportSecureExpModKeyLayout *layout = reinterpret_cast<ImportSecureExpModKeyLayout *>(g_work_buffer);
DecryptAndStoreDeviceUniqueKeyLayout *layout = reinterpret_cast<DecryptAndStoreDeviceUniqueKeyLayout *>(g_work_buffer);
/* Validate size. */
R_UNLESS(src_size <= sizeof(ImportSecureExpModKeyLayout), spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(DecryptAndStoreDeviceUniqueKeyLayout), spl::ResultInvalidSize());
std::memcpy(layout, src, src_size);
armDCacheFlush(layout, sizeof(*layout));
smc::Result smc_res;
if (hos::GetVersion() >= hos::Version_5_0_0) {
smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, static_cast<smc::DecryptOrImportMode>(option));
smc_res = smc::DecryptDeviceUniqueData(layout->data, src_size, access_key, key_source, static_cast<smc::DeviceUniqueDataMode>(option));
} else {
smc_res = smc::ImportSecureExpModKey(layout->data, src_size, access_key, key_source, option);
smc_res = smc::DecryptAndStoreGcKey(layout->data, src_size, access_key, key_source, option);
}
return smc::ConvertResult(smc_res);
}
Result SecureExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size, smc::SecureExpModMode mode) {
struct SecureExpModLayout {
Result ModularExponentiateWithStorageKey(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size, smc::ModularExponentiateWithStorageKeyMode mode) {
struct ModularExponentiateWithStorageKeyLayout {
u8 base[0x100];
u8 mod[0x100];
};
SecureExpModLayout *layout = reinterpret_cast<SecureExpModLayout *>(g_work_buffer);
ModularExponentiateWithStorageKeyLayout *layout = reinterpret_cast<ModularExponentiateWithStorageKeyLayout *>(g_work_buffer);
/* Validate sizes. */
R_UNLESS(base_size <= sizeof(layout->base), spl::ResultInvalidSize());
@@ -443,7 +443,7 @@ namespace ams::spl::impl {
std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key;
smc::Result res = smc::SecureExpMod(&op_key, layout->base, layout->mod, mode);
smc::Result res = smc::ModularExponentiateWithStorageKey(&op_key, layout->base, layout->mod, mode);
if (res != smc::Result::Success) {
return smc::ConvertResult(res);
}
@@ -458,12 +458,12 @@ namespace ams::spl::impl {
return ResultSuccess();
}
Result UnwrapEsRsaOaepWrappedKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation, smc::EsKeyType type) {
struct UnwrapEsKeyLayout {
Result PrepareEsDeviceUniqueKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation, smc::EsCommonKeyType type) {
struct PrepareEsDeviceUniqueKeyLayout {
u8 base[0x100];
u8 mod[0x100];
};
UnwrapEsKeyLayout *layout = reinterpret_cast<UnwrapEsKeyLayout *>(g_work_buffer);
PrepareEsDeviceUniqueKeyLayout *layout = reinterpret_cast<PrepareEsDeviceUniqueKeyLayout *>(g_work_buffer);
/* Validate sizes. */
R_UNLESS(base_size <= sizeof(layout->base), spl::ResultInvalidSize());
@@ -483,7 +483,7 @@ namespace ams::spl::impl {
std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key;
smc::Result res = smc::UnwrapTitleKey(&op_key, layout->base, layout->mod, label_digest, label_digest_size, smc::GetUnwrapEsKeyOption(type, generation));
smc::Result res = smc::PrepareEsDeviceUniqueKey(&op_key, layout->base, layout->mod, label_digest, label_digest_size, smc::GetPrepareEsDeviceUniqueKeyOption(type, generation));
if (res != smc::Result::Success) {
return smc::ConvertResult(res);
}
@@ -514,39 +514,45 @@ namespace ams::spl::impl {
}
/* General. */
Result GetConfig(u64 *out, SplConfigItem which) {
Result GetConfig(u64 *out, ConfigItem which) {
/* Nintendo explicitly blacklists package2 hash here, amusingly. */
/* This is not blacklisted in safemode, but we're never in safe mode... */
R_UNLESS(which != SplConfigItem_Package2Hash, spl::ResultInvalidArgument());
R_UNLESS(which != ConfigItem::Package2Hash, spl::ResultInvalidArgument());
smc::Result res = smc::GetConfig(out, 1, which);
/* Nintendo has some special handling here for hardware type/is_retail. */
if (which == SplConfigItem_HardwareType && res == smc::Result::InvalidArgument) {
*out = 0;
res = smc::Result::Success;
}
if (which == SplConfigItem_IsRetail && res == smc::Result::InvalidArgument) {
*out = 0;
res = smc::Result::Success;
if (res == smc::Result::InvalidArgument) {
switch (which) {
case ConfigItem::HardwareType:
*out = static_cast<u64>(HardwareType::Icosa);
res = smc::Result::Success;
break;
case ConfigItem::HardwareState:
*out = HardwareState_Development;
res = smc::Result::Success;
break;
default:
break;
}
}
return smc::ConvertResult(res);
}
Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size) {
struct ExpModLayout {
Result ModularExponentiate(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size) {
struct ModularExponentiateLayout {
u8 base[0x100];
u8 exp[0x100];
u8 mod[0x100];
};
ExpModLayout *layout = reinterpret_cast<ExpModLayout *>(g_work_buffer);
ModularExponentiateLayout *layout = reinterpret_cast<ModularExponentiateLayout *>(g_work_buffer);
/* Validate sizes. */
R_UNLESS(base_size <= sizeof(layout->base), spl::ResultInvalidSize());
R_UNLESS(exp_size <= sizeof(layout->exp), spl::ResultInvalidSize());
R_UNLESS(mod_size <= sizeof(layout->mod), spl::ResultInvalidSize());
R_UNLESS(out_size <= WorkBufferSizeMax, spl::ResultInvalidSize());
R_UNLESS(exp_size <= sizeof(layout->exp), spl::ResultInvalidSize());
R_UNLESS(mod_size <= sizeof(layout->mod), spl::ResultInvalidSize());
R_UNLESS(out_size <= WorkBufferSizeMax, spl::ResultInvalidSize());
/* Copy data into work buffer. */
const size_t base_ofs = sizeof(layout->base) - base_size;
@@ -562,7 +568,7 @@ namespace ams::spl::impl {
std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key;
smc::Result res = smc::ExpMod(&op_key, layout->base, layout->exp, exp_size, layout->mod);
smc::Result res = smc::ModularExponentiate(&op_key, layout->base, layout->exp, exp_size, layout->mod);
if (res != smc::Result::Success) {
return smc::ConvertResult(res);
}
@@ -577,7 +583,7 @@ namespace ams::spl::impl {
return ResultSuccess();
}
Result SetConfig(SplConfigItem which, u64 value) {
Result SetConfig(ConfigItem which, u64 value) {
return smc::ConvertResult(smc::SetConfig(which, &value, 1));
}
@@ -595,10 +601,10 @@ namespace ams::spl::impl {
}
Result IsDevelopment(bool *out) {
u64 is_retail;
R_TRY(GetConfig(&is_retail, SplConfigItem_IsRetail));
u64 hardware_state;
R_TRY(impl::GetConfig(&hardware_state, ConfigItem::HardwareState));
*out = (is_retail == 0);
*out = (hardware_state == HardwareState_Development);
return ResultSuccess();
}
@@ -623,7 +629,7 @@ namespace ams::spl::impl {
}
Result LoadAesKey(s32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source) {
R_TRY(ValidateAesKeyslot(keyslot, owner));
R_TRY(ValidateAesKeySlot(keyslot, owner));
return LoadVirtualAesKey(keyslot, access_key, key_source);
}
@@ -632,7 +638,7 @@ namespace ams::spl::impl {
.data = {0x89, 0x61, 0x5E, 0xE0, 0x5C, 0x31, 0xB6, 0x80, 0x5F, 0xE5, 0x8F, 0x3D, 0xA2, 0x4F, 0x7A, 0xA8}
};
ScopedAesKeyslot keyslot_holder;
ScopedAesKeySlot keyslot_holder;
R_TRY(keyslot_holder.Allocate());
R_TRY(LoadVirtualAesKey(keyslot_holder.GetKeySlot(), access_key, s_generate_aes_key_source));
@@ -651,8 +657,8 @@ namespace ams::spl::impl {
return GenerateAesKey(out_key, access_key, key_source);
}
Result CryptAesCtr(void *dst, size_t dst_size, s32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr) {
R_TRY(ValidateAesKeyslot(keyslot, owner));
Result ComputeCtr(void *dst, size_t dst_size, s32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr) {
R_TRY(ValidateAesKeySlot(keyslot, owner));
/* Succeed immediately if there's nothing to crypt. */
if (src_size == 0) {
@@ -670,14 +676,14 @@ namespace ams::spl::impl {
const uintptr_t dst_addr_page_aligned = util::AlignDown(dst_addr, os::MemoryPageSize);
const size_t src_size_page_aligned = util::AlignUp(src_addr + src_size, os::MemoryPageSize) - src_addr_page_aligned;
const size_t dst_size_page_aligned = util::AlignUp(dst_addr + dst_size, os::MemoryPageSize) - dst_addr_page_aligned;
const u32 src_se_map_addr = CryptAesInMapBase + (src_addr_page_aligned % DeviceAddressSpaceAlign);
const u32 dst_se_map_addr = CryptAesOutMapBase + (dst_addr_page_aligned % DeviceAddressSpaceAlign);
const u32 src_se_addr = CryptAesInMapBase + (src_addr % DeviceAddressSpaceAlign);
const u32 dst_se_addr = CryptAesOutMapBase + (dst_addr % DeviceAddressSpaceAlign);
const u32 src_se_map_addr = ComputeAesInMapBase + (src_addr_page_aligned % DeviceAddressSpaceAlign);
const u32 dst_se_map_addr = ComputeAesOutMapBase + (dst_addr_page_aligned % DeviceAddressSpaceAlign);
const u32 src_se_addr = ComputeAesInMapBase + (src_addr % DeviceAddressSpaceAlign);
const u32 dst_se_addr = ComputeAesOutMapBase + (dst_addr % DeviceAddressSpaceAlign);
/* Validate aligned sizes. */
R_UNLESS(src_size_page_aligned <= CryptAesSizeMax, spl::ResultInvalidSize());
R_UNLESS(dst_size_page_aligned <= CryptAesSizeMax, spl::ResultInvalidSize());
R_UNLESS(src_size_page_aligned <= ComputeAesSizeMax, spl::ResultInvalidSize());
R_UNLESS(dst_size_page_aligned <= ComputeAesSizeMax, spl::ResultInvalidSize());
/* Helpers for mapping/unmapping. */
DeviceAddressSpaceMapHelper in_mapper(g_se_das_hnd, src_se_map_addr, src_addr_page_aligned, src_size_page_aligned, 1);
@@ -698,11 +704,11 @@ namespace ams::spl::impl {
{
std::scoped_lock lk(g_async_op_lock);
smc::AsyncOperationKey op_key;
const u32 mode = smc::GetCryptAesMode(smc::CipherMode::Ctr, GetPhysicalKeySlot(keyslot, true));
const u32 mode = smc::GetComputeAesMode(smc::CipherMode::Ctr, GetPhysicalKeySlot(keyslot, true));
const u32 dst_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, out);
const u32 src_ll_addr = g_se_mapped_work_buffer_addr + offsetof(SeCryptContext, in);
smc::Result res = smc::CryptAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, src_size);
smc::Result res = smc::ComputeAes(&op_key, mode, iv_ctr, dst_ll_addr, src_ll_addr, src_size);
if (res != smc::Result::Success) {
return smc::ConvertResult(res);
}
@@ -717,7 +723,7 @@ namespace ams::spl::impl {
}
Result ComputeCmac(Cmac *out_cmac, s32 keyslot, const void *owner, const void *data, size_t size) {
R_TRY(ValidateAesKeyslot(keyslot, owner));
R_TRY(ValidateAesKeySlot(keyslot, owner));
R_UNLESS(size <= WorkBufferSizeMax, spl::ResultInvalidSize());
@@ -725,9 +731,9 @@ namespace ams::spl::impl {
return smc::ConvertResult(smc::ComputeCmac(out_cmac, GetPhysicalKeySlot(keyslot, true), g_work_buffer, size));
}
Result AllocateAesKeyslot(s32 *out_keyslot, const void *owner) {
Result AllocateAesKeySlot(s32 *out_keyslot, const void *owner) {
/* Find a virtual keyslot. */
for (s32 i = 0; i < MaxVirtualAesKeyslots; i++) {
for (s32 i = 0; i < MaxVirtualAesKeySlots; i++) {
if (g_keyslot_owners[i] == nullptr) {
g_keyslot_owners[i] = owner;
g_keyslot_contents[i] = { .type = KeySlotContentType::None };
@@ -737,20 +743,20 @@ namespace ams::spl::impl {
}
os::ClearSystemEvent(std::addressof(g_se_keyslot_available_event));
return spl::ResultOutOfKeyslots();
return spl::ResultOutOfKeySlots();
}
Result FreeAesKeyslot(s32 keyslot, const void *owner) {
Result DeallocateAesKeySlot(s32 keyslot, const void *owner) {
/* Only virtual keyslots can be freed. */
R_UNLESS(IsVirtualKeySlot(keyslot), spl::ResultInvalidKeyslot());
R_UNLESS(IsVirtualKeySlot(keyslot), spl::ResultInvalidKeySlot());
/* Ensure the keyslot is owned. */
R_TRY(ValidateAesKeyslot(keyslot, owner));
R_TRY(ValidateAesKeySlot(keyslot, owner));
/* Clear the physical keyslot, if we're cached. */
s32 phys_slot;
if (g_keyslot_cache.Release(std::addressof(phys_slot), keyslot)) {
ClearPhysicalKeyslot(phys_slot);
ClearPhysicalKeySlot(phys_slot);
}
/* Clear the virtual keyslot. */
@@ -763,15 +769,15 @@ namespace ams::spl::impl {
}
/* RSA. */
Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
struct DecryptRsaPrivateKeyLayout {
u8 data[RsaPrivateKeySize + RsaPrivateKeyMetaSize];
Result DecryptDeviceUniqueData(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
struct DecryptDeviceUniqueDataLayout {
u8 data[RsaPrivateKeySize + DeviceUniqueDataMetaSize];
};
DecryptRsaPrivateKeyLayout *layout = reinterpret_cast<DecryptRsaPrivateKeyLayout *>(g_work_buffer);
DecryptDeviceUniqueDataLayout *layout = reinterpret_cast<DecryptDeviceUniqueDataLayout *>(g_work_buffer);
/* Validate size. */
R_UNLESS(src_size >= RsaPrivateKeyMetaSize, spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(DecryptRsaPrivateKeyLayout), spl::ResultInvalidSize());
R_UNLESS(src_size >= DeviceUniqueDataMetaSize, spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(DecryptDeviceUniqueDataLayout), spl::ResultInvalidSize());
std::memcpy(layout->data, src, src_size);
armDCacheFlush(layout, sizeof(*layout));
@@ -779,10 +785,10 @@ namespace ams::spl::impl {
smc::Result smc_res;
size_t copy_size = 0;
if (hos::GetVersion() >= hos::Version_5_0_0) {
copy_size = std::min(dst_size, src_size - RsaPrivateKeyMetaSize);
smc_res = smc::DecryptOrImportRsaPrivateKey(layout->data, src_size, access_key, key_source, static_cast<smc::DecryptOrImportMode>(option));
copy_size = std::min(dst_size, src_size - DeviceUniqueDataMetaSize);
smc_res = smc::DecryptDeviceUniqueData(layout->data, src_size, access_key, key_source, static_cast<smc::DeviceUniqueDataMode>(option));
} else {
smc_res = smc::DecryptRsaPrivateKey(&copy_size, layout->data, src_size, access_key, key_source, option);
smc_res = smc::DecryptDeviceUniqueData(&copy_size, layout->data, src_size, access_key, key_source, option);
copy_size = std::min(dst_size, copy_size);
}
@@ -795,71 +801,66 @@ namespace ams::spl::impl {
}
/* SSL */
Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast<u32>(smc::DecryptOrImportMode::ImportSslKey));
Result DecryptAndStoreSslClientCertKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
return DecryptAndStoreDeviceUniqueKey(src, src_size, access_key, key_source, static_cast<u32>(smc::DeviceUniqueDataMode::DecryptAndStoreSslKey));
}
Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Ssl);
Result ModularExponentiateWithSslClientCertKey(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
return ModularExponentiateWithStorageKey(out, out_size, base, base_size, mod, mod_size, smc::ModularExponentiateWithStorageKeyMode::Ssl);
}
/* ES */
Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
Result LoadEsDeviceKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
if (hos::GetVersion() >= hos::Version_5_0_0) {
return ImportSecureExpModKey(src, src_size, access_key, key_source, option);
return DecryptAndStoreDeviceUniqueKey(src, src_size, access_key, key_source, option);
} else {
struct ImportEsKeyLayout {
u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
struct LoadEsDeviceKeyLayout {
u8 data[DeviceUniqueDataMetaSize + 2 * RsaPrivateKeySize + 0x10];
};
ImportEsKeyLayout *layout = reinterpret_cast<ImportEsKeyLayout *>(g_work_buffer);
LoadEsDeviceKeyLayout *layout = reinterpret_cast<LoadEsDeviceKeyLayout *>(g_work_buffer);
/* Validate size. */
R_UNLESS(src_size <= sizeof(ImportEsKeyLayout), spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(LoadEsDeviceKeyLayout), spl::ResultInvalidSize());
std::memcpy(layout, src, src_size);
armDCacheFlush(layout, sizeof(*layout));
return smc::ConvertResult(smc::ImportEsKey(layout->data, src_size, access_key, key_source, option));
return smc::ConvertResult(smc::LoadEsDeviceKey(layout->data, src_size, access_key, key_source, option));
}
}
Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::TitleKey);
Result PrepareEsTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
return PrepareEsDeviceUniqueKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsCommonKeyType::TitleKey);
}
Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation) {
return smc::ConvertResult(smc::UnwrapCommonTitleKey(out_access_key, key_source, generation));
Result PrepareCommonEsTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation) {
return smc::ConvertResult(smc::PrepareCommonEsTitleKey(out_access_key, key_source, generation));
}
Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
return ImportSecureExpModKey(src, src_size, access_key, key_source, static_cast<u32>(smc::DecryptOrImportMode::ImportDrmKey));
Result DecryptAndStoreDrmDeviceCertKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source) {
return DecryptAndStoreDeviceUniqueKey(src, src_size, access_key, key_source, static_cast<u32>(smc::DeviceUniqueDataMode::DecryptAndStoreDrmDeviceCertKey));
}
Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
return SecureExpMod(out, out_size, base, base_size, mod, mod_size, smc::SecureExpModMode::Drm);
Result ModularExponentiateWithDrmDeviceCertKey(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size) {
return ModularExponentiateWithStorageKey(out, out_size, base, base_size, mod, mod_size, smc::ModularExponentiateWithStorageKeyMode::DrmDeviceCert);
}
Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
return UnwrapEsRsaOaepWrappedKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsKeyType::ElicenseKey);
}
Result LoadElicenseKey(s32 keyslot, const void *owner, const AccessKey &access_key) {
/* Right now, this is just literally the same function as LoadTitleKey in N's impl. */
return LoadTitleKey(keyslot, owner, access_key);
Result PrepareEsArchiveKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation) {
return PrepareEsDeviceUniqueKey(out_access_key, base, base_size, mod, mod_size, label_digest, label_digest_size, generation, smc::EsCommonKeyType::ArchiveKey);
}
/* FS */
Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
return ImportSecureExpModKey(src, src_size, access_key, key_source, option);
Result DecryptAndStoreGcKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option) {
return DecryptAndStoreDeviceUniqueKey(src, src_size, access_key, key_source, option);
}
Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size) {
Result DecryptGcMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size) {
/* Validate sizes. */
R_UNLESS(dst_size <= WorkBufferSizeMax, spl::ResultInvalidSize());
R_UNLESS(label_digest_size == LabelDigestSizeMax, spl::ResultInvalidSize());
/* Nintendo doesn't check this result code, but we will. */
R_TRY(SecureExpMod(g_work_buffer, 0x100, base, base_size, mod, mod_size, smc::SecureExpModMode::Lotus));
R_TRY(ModularExponentiateWithStorageKey(g_work_buffer, 0x100, base, base_size, mod, mod_size, smc::ModularExponentiateWithStorageKeyMode::Gc));
size_t data_size = crypto::DecodeRsa2048OaepSha256(dst, dst_size, label_digest, label_digest_size, g_work_buffer, 0x100);
R_UNLESS(data_size > 0, spl::ResultDecryptionFailed());
@@ -872,9 +873,9 @@ namespace ams::spl::impl {
return smc::ConvertResult(smc::GenerateSpecificAesKey(out_key, key_source, generation, which));
}
Result LoadTitleKey(s32 keyslot, const void *owner, const AccessKey &access_key) {
R_TRY(ValidateAesKeyslot(keyslot, owner));
return LoadVirtualTitleKey(keyslot, access_key);
Result LoadPreparedAesKey(s32 keyslot, const void *owner, const AccessKey &access_key) {
R_TRY(ValidateAesKeySlot(keyslot, owner));
return LoadVirtualPreparedAesKey(keyslot, access_key);
}
Result GetPackage2Hash(void *dst, const size_t size) {
@@ -882,7 +883,7 @@ namespace ams::spl::impl {
R_UNLESS(size >= sizeof(hash), spl::ResultInvalidSize());
smc::Result smc_res;
if ((smc_res = smc::GetConfig(hash, 4, SplConfigItem_Package2Hash)) != smc::Result::Success) {
if ((smc_res = smc::GetConfig(hash, 4, ConfigItem::Package2Hash)) != smc::Result::Success) {
return smc::ConvertResult(smc_res);
}
@@ -891,19 +892,19 @@ namespace ams::spl::impl {
}
/* Manu. */
Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
struct ReEncryptRsaPrivateKeyLayout {
u8 data[RsaPrivateKeyMetaSize + 2 * RsaPrivateKeySize + 0x10];
Result ReencryptDeviceUniqueData(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
struct ReencryptDeviceUniqueDataLayout {
u8 data[DeviceUniqueDataMetaSize + 2 * RsaPrivateKeySize + 0x10];
AccessKey access_key_dec;
KeySource source_dec;
AccessKey access_key_enc;
KeySource source_enc;
};
ReEncryptRsaPrivateKeyLayout *layout = reinterpret_cast<ReEncryptRsaPrivateKeyLayout *>(g_work_buffer);
ReencryptDeviceUniqueDataLayout *layout = reinterpret_cast<ReencryptDeviceUniqueDataLayout *>(g_work_buffer);
/* Validate size. */
R_UNLESS(src_size >= RsaPrivateKeyMetaSize, spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(ReEncryptRsaPrivateKeyLayout), spl::ResultInvalidSize());
R_UNLESS(src_size >= DeviceUniqueDataMetaSize, spl::ResultInvalidSize());
R_UNLESS(src_size <= sizeof(ReencryptDeviceUniqueDataLayout), spl::ResultInvalidSize());
std::memcpy(layout, src, src_size);
layout->access_key_dec = access_key_dec;
@@ -913,7 +914,7 @@ namespace ams::spl::impl {
armDCacheFlush(layout, sizeof(*layout));
smc::Result smc_res = smc::ReEncryptRsaPrivateKey(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option);
smc::Result smc_res = smc::ReencryptDeviceUniqueData(layout->data, src_size, layout->access_key_dec, layout->source_dec, layout->access_key_enc, layout->source_enc, option);
if (smc_res == smc::Result::Success) {
size_t copy_size = std::min(dst_size, src_size);
armDCacheFlush(layout, copy_size);
@@ -924,16 +925,16 @@ namespace ams::spl::impl {
}
/* Helper. */
Result FreeAesKeyslots(const void *owner) {
Result DeallocateAllAesKeySlots(const void *owner) {
for (s32 slot = VirtualKeySlotMin; slot <= VirtualKeySlotMax; ++slot) {
if (g_keyslot_owners[GetVirtualKeySlotIndex(slot)] == owner) {
FreeAesKeyslot(slot, owner);
DeallocateAesKeySlot(slot, owner);
}
}
return ResultSuccess();
}
Handle GetAesKeyslotAvailableEventHandle() {
Handle GetAesKeySlotAvailableEventHandle() {
return os::GetReadableHandleOfSystemEvent(std::addressof(g_se_keyslot_available_event));
}

View File

@@ -22,9 +22,9 @@ namespace ams::spl::impl {
void Initialize();
/* General. */
Result GetConfig(u64 *out, SplConfigItem which);
Result ExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size);
Result SetConfig(SplConfigItem which, u64 value);
Result GetConfig(u64 *out, spl::ConfigItem which);
Result ModularExponentiate(void *out, size_t out_size, const void *base, size_t base_size, const void *exp, size_t exp_size, const void *mod, size_t mod_size);
Result SetConfig(spl::ConfigItem which, u64 value);
Result GenerateRandomBytes(void *out, size_t size);
Result IsDevelopment(bool *out);
Result SetBootReason(BootReasonValue boot_reason);
@@ -35,39 +35,39 @@ namespace ams::spl::impl {
Result LoadAesKey(s32 keyslot, const void *owner, const AccessKey &access_key, const KeySource &key_source);
Result GenerateAesKey(AesKey *out_key, const AccessKey &access_key, const KeySource &key_source);
Result DecryptAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 option);
Result CryptAesCtr(void *dst, size_t dst_size, s32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr);
Result ComputeCtr(void *dst, size_t dst_size, s32 keyslot, const void *owner, const void *src, size_t src_size, const IvCtr &iv_ctr);
Result ComputeCmac(Cmac *out_cmac, s32 keyslot, const void *owner, const void *data, size_t size);
Result AllocateAesKeyslot(s32 *out_keyslot, const void *owner);
Result FreeAesKeyslot(s32 keyslot, const void *owner);
Result AllocateAesKeySlot(s32 *out_keyslot, const void *owner);
Result DeallocateAesKeySlot(s32 keyslot, const void *owner);
/* RSA. */
Result DecryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
Result DecryptDeviceUniqueData(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
/* SSL */
Result ImportSslKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
Result SslExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
Result DecryptAndStoreSslClientCertKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
Result ModularExponentiateWithSslClientCertKey(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
/* ES */
Result ImportEsKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
Result UnwrapTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
Result UnwrapCommonTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation);
Result ImportDrmKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
Result DrmExpMod(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
Result UnwrapElicenseKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
Result LoadElicenseKey(s32 keyslot, const void *owner, const AccessKey &access_key);
Result LoadEsDeviceKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
Result PrepareEsTitleKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
Result PrepareCommonEsTitleKey(AccessKey *out_access_key, const KeySource &key_source, u32 generation);
Result DecryptAndStoreDrmDeviceCertKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source);
Result ModularExponentiateWithDrmDeviceCertKey(void *out, size_t out_size, const void *base, size_t base_size, const void *mod, size_t mod_size);
Result PrepareEsArchiveKey(AccessKey *out_access_key, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size, u32 generation);
Result LoadPreparedAesKey(s32 keyslot, const void *owner, const AccessKey &access_key);
/* FS */
Result ImportLotusKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
Result DecryptLotusMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size);
Result DecryptAndStoreGcKey(const void *src, size_t src_size, const AccessKey &access_key, const KeySource &key_source, u32 option);
Result DecryptGcMessage(u32 *out_size, void *dst, size_t dst_size, const void *base, size_t base_size, const void *mod, size_t mod_size, const void *label_digest, size_t label_digest_size);
Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &key_source, u32 generation, u32 which);
Result LoadTitleKey(s32 keyslot, const void *owner, const AccessKey &access_key);
Result LoadPreparedAesKey(s32 keyslot, const void *owner, const AccessKey &access_key);
Result GetPackage2Hash(void *dst, const size_t size);
/* Manu. */
Result ReEncryptRsaPrivateKey(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option);
Result ReencryptDeviceUniqueData(void *dst, size_t dst_size, const void *src, size_t src_size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option);
/* Helper. */
Result FreeAesKeyslots(const void *owner);
Handle GetAesKeyslotAvailableEventHandle();
Result DeallocateAllAesKeySlots(const void *owner);
Handle GetAesKeySlotAvailableEventHandle();
}

View File

@@ -21,7 +21,7 @@ namespace ams::spl {
CryptoService::~CryptoService() {
/* Free any keyslots this service is using. */
impl::FreeAesKeyslots(this);
impl::DeallocateAllAesKeySlots(this);
}
Result CryptoService::GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option) {
@@ -40,24 +40,25 @@ namespace ams::spl {
return impl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
}
Result CryptoService::CryptAesCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr) {
return impl::CryptAesCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
Result CryptoService::ComputeCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr) {
return impl::ComputeCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
}
Result CryptoService::ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf) {
return impl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize());
}
Result CryptoService::AllocateAesKeyslot(sf::Out<s32> out_keyslot) {
return impl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
Result CryptoService::AllocateAesKeySlot(sf::Out<s32> out_keyslot) {
return impl::AllocateAesKeySlot(out_keyslot.GetPointer(), this);
}
Result CryptoService::FreeAesKeyslot(s32 keyslot) {
return impl::FreeAesKeyslot(keyslot, this);
Result CryptoService::DeallocateAesKeySlot(s32 keyslot) {
return impl::DeallocateAesKeySlot(keyslot, this);
}
void CryptoService::GetAesKeyslotAvailableEvent(sf::OutCopyHandle out_hnd) {
out_hnd.SetValue(impl::GetAesKeyslotAvailableEventHandle());
Result CryptoService::GetAesKeySlotAvailableEvent(sf::OutCopyHandle out_hnd) {
out_hnd.SetValue(impl::GetAesKeySlotAvailableEventHandle());
return ResultSuccess();
}
}

View File

@@ -20,38 +20,19 @@ namespace ams::spl {
class CryptoService : public GeneralService {
public:
CryptoService() : GeneralService() { /* ... */ }
virtual ~CryptoService();
protected:
/* Actual commands. */
virtual Result GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option);
virtual Result LoadAesKey(s32 keyslot, AccessKey access_key, KeySource key_source);
virtual Result GenerateAesKey(sf::Out<AesKey> out_key, AccessKey access_key, KeySource key_source);
virtual Result DecryptAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 option);
virtual Result CryptAesCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr);
virtual Result ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf);
virtual Result AllocateAesKeyslot(sf::Out<s32> out_keyslot);
virtual Result FreeAesKeyslot(s32 keyslot);
virtual void GetAesKeyslotAvailableEvent(sf::OutCopyHandle out_hnd);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtr),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
};
/* Actual commands. */
Result GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option);
Result LoadAesKey(s32 keyslot, AccessKey access_key, KeySource key_source);
Result GenerateAesKey(sf::Out<AesKey> out_key, AccessKey access_key, KeySource key_source);
Result DecryptAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 option);
Result ComputeCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr);
Result ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf);
Result AllocateAesKeySlot(sf::Out<s32> out_keyslot);
Result DeallocateAesKeySlot(s32 keyslot);
Result GetAesKeySlotAvailableEvent(sf::OutCopyHandle out_hnd);
};
static_assert(spl::impl::IsICryptoInterface<CryptoService>);
}

View File

@@ -19,12 +19,17 @@
namespace ams::spl {
Result DeprecatedService::GetConfig(sf::Out<u64> out, u32 which) {
return impl::GetConfig(out.GetPointer(), static_cast<SplConfigItem>(which));
DeprecatedService::~DeprecatedService() {
/* Free any keyslots this service is using. */
impl::DeallocateAllAesKeySlots(this);
}
Result DeprecatedService::ExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod) {
return impl::ExpMod(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), exp.GetPointer(), exp.GetSize(), mod.GetPointer(), mod.GetSize());
Result DeprecatedService::GetConfig(sf::Out<u64> out, u32 which) {
return impl::GetConfig(out.GetPointer(), static_cast<spl::ConfigItem>(which));
}
Result DeprecatedService::ModularExponentiate(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod) {
return impl::ModularExponentiate(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), exp.GetPointer(), exp.GetSize(), mod.GetPointer(), mod.GetSize());
}
Result DeprecatedService::GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option) {
@@ -40,19 +45,19 @@ namespace ams::spl {
}
Result DeprecatedService::SetConfig(u32 which, u64 value) {
return impl::SetConfig(static_cast<SplConfigItem>(which), value);
return impl::SetConfig(static_cast<spl::ConfigItem>(which), value);
}
Result DeprecatedService::GenerateRandomBytes(const sf::OutPointerBuffer &out) {
return impl::GenerateRandomBytes(out.GetPointer(), out.GetSize());
}
Result DeprecatedService::ImportLotusKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::ImportLotusKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
Result DeprecatedService::DecryptAndStoreGcKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptAndStoreGcKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result DeprecatedService::DecryptLotusMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::DecryptLotusMessage(out_size.GetPointer(), out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize());
Result DeprecatedService::DecryptGcMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::DecryptGcMessage(out_size.GetPointer(), out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize());
}
Result DeprecatedService::IsDevelopment(sf::Out<bool> is_dev) {
@@ -63,60 +68,61 @@ namespace ams::spl {
return impl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
}
Result DeprecatedService::DecryptRsaPrivateKey(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptRsaPrivateKey(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, option);
Result DeprecatedService::DecryptDeviceUniqueData(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptDeviceUniqueData(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result DeprecatedService::DecryptAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 option) {
return impl::DecryptAesKey(out_key.GetPointer(), key_source, generation, option);
}
Result DeprecatedService::CryptAesCtrDeprecated(const sf::OutBuffer &out_buf, s32 keyslot, const sf::InBuffer &in_buf, IvCtr iv_ctr) {
return impl::CryptAesCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
Result DeprecatedService::ComputeCtrDeprecated(const sf::OutBuffer &out_buf, s32 keyslot, const sf::InBuffer &in_buf, IvCtr iv_ctr) {
return impl::ComputeCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
}
Result DeprecatedService::CryptAesCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr) {
return impl::CryptAesCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
Result DeprecatedService::ComputeCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr) {
return impl::ComputeCtr(out_buf.GetPointer(), out_buf.GetSize(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize(), iv_ctr);
}
Result DeprecatedService::ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf) {
return impl::ComputeCmac(out_cmac.GetPointer(), keyslot, this, in_buf.GetPointer(), in_buf.GetSize());
}
Result DeprecatedService::ImportEsKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::ImportEsKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
Result DeprecatedService::LoadEsDeviceKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::LoadEsDeviceKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result DeprecatedService::UnwrapTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::UnwrapTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), 0);
Result DeprecatedService::PrepareEsTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::PrepareEsTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), 0);
}
Result DeprecatedService::UnwrapTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::UnwrapTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
Result DeprecatedService::PrepareEsTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::PrepareEsTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
}
Result DeprecatedService::LoadTitleKey(s32 keyslot, AccessKey access_key) {
return impl::LoadTitleKey(keyslot, this, access_key);
Result DeprecatedService::LoadPreparedAesKey(s32 keyslot, AccessKey access_key) {
return impl::LoadPreparedAesKey(keyslot, this, access_key);
}
Result DeprecatedService::UnwrapCommonTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, KeySource key_source) {
return impl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, 0);
Result DeprecatedService::PrepareCommonEsTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, KeySource key_source) {
return impl::PrepareCommonEsTitleKey(out_access_key.GetPointer(), key_source, 0);
}
Result DeprecatedService::UnwrapCommonTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation) {
return impl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
Result DeprecatedService::PrepareCommonEsTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation) {
return impl::PrepareCommonEsTitleKey(out_access_key.GetPointer(), key_source, generation);
}
Result DeprecatedService::AllocateAesKeyslot(sf::Out<s32> out_keyslot) {
return impl::AllocateAesKeyslot(out_keyslot.GetPointer(), this);
Result DeprecatedService::AllocateAesKeySlot(sf::Out<s32> out_keyslot) {
return impl::AllocateAesKeySlot(out_keyslot.GetPointer(), this);
}
Result DeprecatedService::FreeAesKeyslot(s32 keyslot) {
return impl::FreeAesKeyslot(keyslot, this);
Result DeprecatedService::DeallocateAesKeySlot(s32 keyslot) {
return impl::DeallocateAesKeySlot(keyslot, this);
}
void DeprecatedService::GetAesKeyslotAvailableEvent(sf::OutCopyHandle out_hnd) {
out_hnd.SetValue(impl::GetAesKeyslotAvailableEventHandle());
Result DeprecatedService::GetAesKeySlotAvailableEvent(sf::OutCopyHandle out_hnd) {
out_hnd.SetValue(impl::GetAesKeySlotAvailableEventHandle());
return ResultSuccess();
}
Result DeprecatedService::SetBootReason(BootReasonValue boot_reason) {

View File

@@ -18,112 +18,39 @@
namespace ams::spl {
class DeprecatedService : public sf::IServiceObject {
protected:
enum class CommandId {
/* 1.0.0+ */
GetConfig = 0,
ExpMod = 1,
GenerateAesKek = 2,
LoadAesKey = 3,
GenerateAesKey = 4,
SetConfig = 5,
GenerateRandomBytes = 7,
ImportLotusKey = 9,
DecryptLotusMessage = 10,
IsDevelopment = 11,
GenerateSpecificAesKey = 12,
DecryptRsaPrivateKeyDeprecated = 13,
DecryptRsaPrivateKey = 13,
DecryptAesKey = 14,
CryptAesCtrDeprecated = 15,
CryptAesCtr = 15,
ComputeCmac = 16,
ImportEsKey = 17,
UnwrapTitleKeyDeprecated = 18,
UnwrapTitleKey = 18,
LoadTitleKey = 19,
/* 2.0.0+ */
UnwrapCommonTitleKeyDeprecated = 20,
UnwrapCommonTitleKey = 20,
AllocateAesKeyslot = 21,
FreeAesKeyslot = 22,
GetAesKeyslotAvailableEvent = 23,
/* 3.0.0+ */
SetBootReason = 24,
GetBootReason = 25,
};
class DeprecatedService final {
public:
virtual ~DeprecatedService();
public:
DeprecatedService() { /* ... */ }
virtual ~DeprecatedService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result GetConfig(sf::Out<u64> out, u32 which);
virtual Result ExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod);
virtual Result GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option);
virtual Result LoadAesKey(s32 keyslot, AccessKey access_key, KeySource key_source);
virtual Result GenerateAesKey(sf::Out<AesKey> out_key, AccessKey access_key, KeySource key_source);
virtual Result SetConfig(u32 which, u64 value);
virtual Result GenerateRandomBytes(const sf::OutPointerBuffer &out);
virtual Result ImportLotusKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result DecryptLotusMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
virtual Result IsDevelopment(sf::Out<bool> is_dev);
virtual Result GenerateSpecificAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 which);
virtual Result DecryptRsaPrivateKey(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result DecryptAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 option);
virtual Result CryptAesCtrDeprecated(const sf::OutBuffer &out_buf, s32 keyslot, const sf::InBuffer &in_buf, IvCtr iv_ctr);
virtual Result CryptAesCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr);
virtual Result ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf);
virtual Result ImportEsKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result UnwrapTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
virtual Result UnwrapTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
virtual Result LoadTitleKey(s32 keyslot, AccessKey access_key);
virtual Result UnwrapCommonTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, KeySource key_source);
virtual Result UnwrapCommonTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation);
virtual Result AllocateAesKeyslot(sf::Out<s32> out_keyslot);
virtual Result FreeAesKeyslot(s32 keyslot);
virtual void GetAesKeyslotAvailableEvent(sf::OutCopyHandle out_hnd);
virtual Result SetBootReason(BootReasonValue boot_reason);
virtual Result GetBootReason(sf::Out<BootReasonValue> out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(ImportLotusKey),
MAKE_SERVICE_COMMAND_META(DecryptLotusMessage),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(GenerateSpecificAesKey),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtrDeprecated, hos::Version_1_0_0, hos::Version_1_0_0),
MAKE_SERVICE_COMMAND_META(CryptAesCtr, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(ImportEsKey),
MAKE_SERVICE_COMMAND_META(UnwrapTitleKeyDeprecated, hos::Version_1_0_0, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(UnwrapTitleKey, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(LoadTitleKey),
MAKE_SERVICE_COMMAND_META(UnwrapCommonTitleKeyDeprecated, hos::Version_2_0_0, hos::Version_2_3_0),
MAKE_SERVICE_COMMAND_META(UnwrapCommonTitleKey, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent /* Atmosphere extension: This was added in hos::Version_2_0_0, but is allowed on older firmware by atmosphere. */),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
};
Result GetConfig(sf::Out<u64> out, u32 which);
Result ModularExponentiate(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod);
Result GenerateAesKek(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation, u32 option);
Result LoadAesKey(s32 keyslot, AccessKey access_key, KeySource key_source);
Result GenerateAesKey(sf::Out<AesKey> out_key, AccessKey access_key, KeySource key_source);
Result SetConfig(u32 which, u64 value);
Result GenerateRandomBytes(const sf::OutPointerBuffer &out);
Result DecryptAndStoreGcKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result DecryptGcMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
Result IsDevelopment(sf::Out<bool> is_dev);
Result GenerateSpecificAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 which);
Result DecryptDeviceUniqueData(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result DecryptAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 option);
Result ComputeCtrDeprecated(const sf::OutBuffer &out_buf, s32 keyslot, const sf::InBuffer &in_buf, IvCtr iv_ctr);
Result ComputeCtr(const sf::OutNonSecureBuffer &out_buf, s32 keyslot, const sf::InNonSecureBuffer &in_buf, IvCtr iv_ctr);
Result ComputeCmac(sf::Out<Cmac> out_cmac, s32 keyslot, const sf::InPointerBuffer &in_buf);
Result LoadEsDeviceKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result PrepareEsTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
Result PrepareEsTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
Result LoadPreparedAesKey(s32 keyslot, AccessKey access_key);
Result PrepareCommonEsTitleKeyDeprecated(sf::Out<AccessKey> out_access_key, KeySource key_source);
Result PrepareCommonEsTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation);
Result AllocateAesKeySlot(sf::Out<s32> out_keyslot);
Result DeallocateAesKeySlot(s32 keyslot);
Result GetAesKeySlotAvailableEvent(sf::OutCopyHandle out_hnd);
Result SetBootReason(BootReasonValue boot_reason);
Result GetBootReason(sf::Out<BootReasonValue> out);
};
static_assert(spl::impl::IsIDeprecatedGeneralInterface<DeprecatedService>);
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
#include "spl_api_impl.hpp"
#include "spl_device_unique_data_service.hpp"
namespace ams::spl {
Result DeviceUniqueDataService::DecryptDeviceUniqueDataDeprecated(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptDeviceUniqueData(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result DeviceUniqueDataService::DecryptDeviceUniqueData(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::DecryptDeviceUniqueData(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DeviceUniqueDataMode::DecryptDeviceUniqueData));
}
}

View File

@@ -18,14 +18,12 @@
namespace ams::spl {
class RsaService : public CryptoService {
class DeviceUniqueDataService : public CryptoService {
public:
RsaService() : CryptoService() { /* ... */ }
virtual ~RsaService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result DecryptRsaPrivateKeyDeprecated(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result DecryptRsaPrivateKey(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
Result DecryptDeviceUniqueDataDeprecated(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result DecryptDeviceUniqueData(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
};
static_assert(spl::impl::IsIDeviceUniqueDataInterface<DeviceUniqueDataService>);
}

View File

@@ -19,36 +19,36 @@
namespace ams::spl {
Result EsService::ImportEsKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::ImportEsKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
Result EsService::LoadEsDeviceKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::LoadEsDeviceKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result EsService::ImportEsKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::ImportEsKey(src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DecryptOrImportMode::ImportEsKey));
Result EsService::LoadEsDeviceKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::LoadEsDeviceKey(src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DeviceUniqueDataMode::DecryptAndStoreEsDeviceKey));
}
Result EsService::UnwrapTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::UnwrapTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
Result EsService::PrepareEsTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::PrepareEsTitleKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
}
Result EsService::UnwrapCommonTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation) {
return impl::UnwrapCommonTitleKey(out_access_key.GetPointer(), key_source, generation);
Result EsService::PrepareCommonEsTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation) {
return impl::PrepareCommonEsTitleKey(out_access_key.GetPointer(), key_source, generation);
}
Result EsService::ImportDrmKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::ImportDrmKey(src.GetPointer(), src.GetSize(), access_key, key_source);
Result EsService::DecryptAndStoreDrmDeviceCertKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::DecryptAndStoreDrmDeviceCertKey(src.GetPointer(), src.GetSize(), access_key, key_source);
}
Result EsService::DrmExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod) {
return impl::DrmExpMod(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize());
Result EsService::ModularExponentiateWithDrmDeviceCertKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod) {
return impl::ModularExponentiateWithDrmDeviceCertKey(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize());
}
Result EsService::UnwrapElicenseKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::UnwrapElicenseKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
Result EsService::PrepareEsArchiveKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation) {
return impl::PrepareEsArchiveKey(out_access_key.GetPointer(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize(), generation);
}
Result EsService::LoadElicenseKey(s32 keyslot, AccessKey access_key) {
return impl::LoadElicenseKey(keyslot, this, access_key);
Result EsService::LoadPreparedAesKey(s32 keyslot, AccessKey access_key) {
return impl::LoadPreparedAesKey(keyslot, this, access_key);
}
}

View File

@@ -14,53 +14,22 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "spl_rsa_service.hpp"
#include "spl_device_unique_data_service.hpp"
namespace ams::spl {
class EsService : public RsaService {
class EsService : public DeviceUniqueDataService {
public:
EsService() : RsaService() { /* ... */ }
virtual ~EsService() { /* ... */}
protected:
/* Actual commands. */
virtual Result ImportEsKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result ImportEsKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
virtual Result UnwrapTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
virtual Result UnwrapCommonTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation);
virtual Result ImportDrmKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
virtual Result DrmExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod);
virtual Result UnwrapElicenseKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
virtual Result LoadElicenseKey(s32 keyslot, AccessKey access_key);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtr),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKeyDeprecated, hos::Version_4_0_0, hos::Version_4_1_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(ImportEsKeyDeprecated, hos::Version_4_0_0, hos::Version_4_1_0),
MAKE_SERVICE_COMMAND_META(ImportEsKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(UnwrapTitleKey),
MAKE_SERVICE_COMMAND_META(UnwrapCommonTitleKey, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(ImportDrmKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(DrmExpMod, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(UnwrapElicenseKey, hos::Version_6_0_0),
MAKE_SERVICE_COMMAND_META(LoadElicenseKey, hos::Version_6_0_0),
};
Result LoadEsDeviceKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result LoadEsDeviceKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
Result PrepareEsTitleKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
Result PrepareCommonEsTitleKey(sf::Out<AccessKey> out_access_key, KeySource key_source, u32 generation);
Result DecryptAndStoreDrmDeviceCertKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
Result ModularExponentiateWithDrmDeviceCertKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod);
Result PrepareEsArchiveKey(sf::Out<AccessKey> out_access_key, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest, u32 generation);
Result LoadPreparedAesKey(s32 keyslot, AccessKey access_key);
};
static_assert(spl::impl::IsIEsInterface<EsService>);
}

View File

@@ -19,24 +19,24 @@
namespace ams::spl {
Result FsService::ImportLotusKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::ImportLotusKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
Result FsService::DecryptAndStoreGcKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptAndStoreGcKey(src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result FsService::ImportLotusKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::ImportLotusKey(src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DecryptOrImportMode::ImportLotusKey));
Result FsService::DecryptAndStoreGcKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::DecryptAndStoreGcKey(src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DeviceUniqueDataMode::DecryptAndStoreGcKey));
}
Result FsService::DecryptLotusMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::DecryptLotusMessage(out_size.GetPointer(), out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize());
Result FsService::DecryptGcMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest) {
return impl::DecryptGcMessage(out_size.GetPointer(), out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize(), label_digest.GetPointer(), label_digest.GetSize());
}
Result FsService::GenerateSpecificAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 which) {
return impl::GenerateSpecificAesKey(out_key.GetPointer(), key_source, generation, which);
}
Result FsService::LoadTitleKey(s32 keyslot, AccessKey access_key) {
return impl::LoadTitleKey(keyslot, this, access_key);
Result FsService::LoadPreparedAesKey(s32 keyslot, AccessKey access_key) {
return impl::LoadPreparedAesKey(keyslot, this, access_key);
}
Result FsService::GetPackage2Hash(const sf::OutPointerBuffer &dst) {

View File

@@ -20,41 +20,14 @@ namespace ams::spl {
class FsService : public CryptoService {
public:
FsService() : CryptoService() { /* ... */ }
virtual ~FsService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result ImportLotusKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
virtual Result ImportLotusKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
virtual Result DecryptLotusMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
virtual Result GenerateSpecificAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 which);
virtual Result LoadTitleKey(s32 keyslot, AccessKey access_key);
virtual Result GetPackage2Hash(const sf::OutPointerBuffer &dst);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtr),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(ImportLotusKeyDeprecated, hos::Version_4_0_0, hos::Version_4_1_0),
MAKE_SERVICE_COMMAND_META(ImportLotusKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(DecryptLotusMessage),
MAKE_SERVICE_COMMAND_META(GenerateSpecificAesKey),
MAKE_SERVICE_COMMAND_META(LoadTitleKey),
MAKE_SERVICE_COMMAND_META(GetPackage2Hash, hos::Version_5_0_0),
};
Result DecryptAndStoreGcKeyDeprecated(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option);
Result DecryptAndStoreGcKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
Result DecryptGcMessage(sf::Out<u32> out_size, const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod, const sf::InPointerBuffer &label_digest);
Result GenerateSpecificAesKey(sf::Out<AesKey> out_key, KeySource key_source, u32 generation, u32 which);
Result LoadPreparedAesKey(s32 keyslot, AccessKey access_key);
Result GetPackage2Hash(const sf::OutPointerBuffer &dst);
};
static_assert(spl::impl::IsIFsInterface<FsService>);
}

View File

@@ -20,15 +20,15 @@
namespace ams::spl {
Result GeneralService::GetConfig(sf::Out<u64> out, u32 which) {
return impl::GetConfig(out.GetPointer(), static_cast<SplConfigItem>(which));
return impl::GetConfig(out.GetPointer(), static_cast<spl::ConfigItem>(which));
}
Result GeneralService::ExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod) {
return impl::ExpMod(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), exp.GetPointer(), exp.GetSize(), mod.GetPointer(), mod.GetSize());
Result GeneralService::ModularExponentiate(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod) {
return impl::ModularExponentiate(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), exp.GetPointer(), exp.GetSize(), mod.GetPointer(), mod.GetSize());
}
Result GeneralService::SetConfig(u32 which, u64 value) {
return impl::SetConfig(static_cast<SplConfigItem>(which), value);
return impl::SetConfig(static_cast<spl::ConfigItem>(which), value);
}
Result GeneralService::GenerateRandomBytes(const sf::OutPointerBuffer &out) {

View File

@@ -18,76 +18,17 @@
namespace ams::spl {
class GeneralService : public sf::IServiceObject {
protected:
enum class CommandId {
/* 1.0.0+ */
GetConfig = 0,
ExpMod = 1,
GenerateAesKek = 2,
LoadAesKey = 3,
GenerateAesKey = 4,
SetConfig = 5,
GenerateRandomBytes = 7,
ImportLotusKeyDeprecated = 9,
ImportLotusKey = 9,
DecryptLotusMessage = 10,
IsDevelopment = 11,
GenerateSpecificAesKey = 12,
DecryptRsaPrivateKeyDeprecated = 13,
DecryptRsaPrivateKey = 13,
DecryptAesKey = 14,
CryptAesCtr = 15,
ComputeCmac = 16,
ImportEsKeyDeprecated = 17,
ImportEsKey = 17,
UnwrapTitleKey = 18,
LoadTitleKey = 19,
/* 2.0.0+ */
UnwrapCommonTitleKey = 20,
AllocateAesKeyslot = 21,
FreeAesKeyslot = 22,
GetAesKeyslotAvailableEvent = 23,
/* 3.0.0+ */
SetBootReason = 24,
GetBootReason = 25,
/* 5.0.0+ */
ImportSslKey = 26,
SslExpMod = 27,
ImportDrmKey = 28,
DrmExpMod = 29,
ReEncryptRsaPrivateKey = 30,
GetPackage2Hash = 31,
/* 6.0.0+ */
UnwrapElicenseKey = 31, /* re-used command id :( */
LoadElicenseKey = 32,
};
class GeneralService {
public:
GeneralService() { /* ... */ }
virtual ~GeneralService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result GetConfig(sf::Out<u64> out, u32 which);
virtual Result ExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod);
virtual Result SetConfig(u32 which, u64 value);
virtual Result GenerateRandomBytes(const sf::OutPointerBuffer &out);
virtual Result IsDevelopment(sf::Out<bool> is_dev);
virtual Result SetBootReason(BootReasonValue boot_reason);
virtual Result GetBootReason(sf::Out<BootReasonValue> out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
};
Result GetConfig(sf::Out<u64> out, u32 which);
Result ModularExponentiate(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &exp, const sf::InPointerBuffer &mod);
Result SetConfig(u32 which, u64 value);
Result GenerateRandomBytes(const sf::OutPointerBuffer &out);
Result IsDevelopment(sf::Out<bool> is_dev);
Result SetBootReason(BootReasonValue boot_reason);
Result GetBootReason(sf::Out<BootReasonValue> out);
};
static_assert(spl::impl::IsIGeneralInterface<GeneralService>);
}

View File

@@ -138,18 +138,18 @@ int main(int argc, char **argv)
spl::impl::Initialize();
/* Create services. */
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::RandomService>(RandomServiceName, RandomMaxSessions));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IRandomInterface, spl::RandomService>(RandomServiceName, RandomMaxSessions)));
if (hos::GetVersion() >= hos::Version_4_0_0) {
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::GeneralService>(GeneralServiceName, GeneralMaxSessions));
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::CryptoService>(CryptoServiceName, CryptoMaxSessions));
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::SslService>(SslServiceName, SslMaxSessions));
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::EsService>(EsServiceName, EsMaxSessions));
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::FsService>(FsServiceName, FsMaxSessions));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IGeneralInterface, spl::GeneralService>(GeneralServiceName, GeneralMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::ICryptoInterface, spl::CryptoService>(CryptoServiceName, CryptoMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::ISslInterface, spl::SslService>(SslServiceName, SslMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IEsInterface, spl::EsService>(EsServiceName, EsMaxSessions)));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IFsInterface, spl::FsService>(FsServiceName, FsMaxSessions)));
if (hos::GetVersion() >= hos::Version_5_0_0) {
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::ManuService>(ManuServiceName, ManuMaxSessions));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IManuInterface, spl::ManuService>(ManuServiceName, ManuMaxSessions)));
}
} else {
R_ABORT_UNLESS(g_server_manager.RegisterServer<spl::DeprecatedService>(DeprecatedServiceName, DeprecatedMaxSessions));
R_ABORT_UNLESS((g_server_manager.RegisterServer<spl::impl::IDeprecatedGeneralInterface, spl::DeprecatedService>(DeprecatedServiceName, DeprecatedMaxSessions)));
}
/* Loop forever, servicing our services. */

View File

@@ -19,8 +19,8 @@
namespace ams::spl {
Result ManuService::ReEncryptRsaPrivateKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option) {
return impl::ReEncryptRsaPrivateKey(out.GetPointer(), out.GetSize(), src.GetPointer(), src.GetSize(), access_key_dec, source_dec, access_key_enc, source_enc, option);
Result ManuService::ReencryptDeviceUniqueData(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option) {
return impl::ReencryptDeviceUniqueData(out.GetPointer(), out.GetSize(), src.GetPointer(), src.GetSize(), access_key_dec, source_dec, access_key_enc, source_enc, option);
}
}

View File

@@ -14,40 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "spl_rsa_service.hpp"
#include "spl_device_unique_data_service.hpp"
namespace ams::spl {
class ManuService : public RsaService {
class ManuService : public DeviceUniqueDataService {
public:
ManuService() : RsaService() { /* ... */ }
virtual ~ManuService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result ReEncryptRsaPrivateKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtr),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKeyDeprecated, hos::Version_4_0_0, hos::Version_4_1_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(ReEncryptRsaPrivateKey, hos::Version_5_0_0),
};
Result ReencryptDeviceUniqueData(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &src, AccessKey access_key_dec, KeySource source_dec, AccessKey access_key_enc, KeySource source_enc, u32 option);
};
static_assert(spl::impl::IsIManuInterface<ManuService>);
}

View File

@@ -18,21 +18,11 @@
namespace ams::spl {
class RandomService final : public sf::IServiceObject {
protected:
enum class CommandId {
GenerateRandomBytes = 0,
};
class RandomService final {
public:
RandomService() { /* ... */ }
virtual ~RandomService() { /* ... */ }
private:
/* Actual commands. */
virtual Result GenerateRandomBytes(const sf::OutBuffer &out);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
};
Result GenerateRandomBytes(const sf::OutBuffer &out);
};
static_assert(spl::impl::IsIRandomInterface<RandomService>);
}

View File

@@ -1,30 +0,0 @@
/*
* Copyright (c) 2018-2020 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 <stratosphere.hpp>
#include "spl_api_impl.hpp"
#include "spl_rsa_service.hpp"
namespace ams::spl {
Result RsaService::DecryptRsaPrivateKeyDeprecated(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source, u32 option) {
return impl::DecryptRsaPrivateKey(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, option);
}
Result RsaService::DecryptRsaPrivateKey(const sf::OutPointerBuffer &dst, const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::DecryptRsaPrivateKey(dst.GetPointer(), dst.GetSize(), src.GetPointer(), src.GetSize(), access_key, key_source, static_cast<u32>(smc::DecryptOrImportMode::DecryptRsaPrivateKey));
}
}

View File

@@ -19,12 +19,12 @@
namespace ams::spl {
Result SslService::ImportSslKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::ImportSslKey(src.GetPointer(), src.GetSize(), access_key, key_source);
Result SslService::DecryptAndStoreSslClientCertKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source) {
return impl::DecryptAndStoreSslClientCertKey(src.GetPointer(), src.GetSize(), access_key, key_source);
}
Result SslService::SslExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod) {
return impl::SslExpMod(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize());
Result SslService::ModularExponentiateWithSslClientCertKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod) {
return impl::ModularExponentiateWithSslClientCertKey(out.GetPointer(), out.GetSize(), base.GetPointer(), base.GetSize(), mod.GetPointer(), mod.GetSize());
}
}

View File

@@ -14,42 +14,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "spl_rsa_service.hpp"
#include "spl_device_unique_data_service.hpp"
namespace ams::spl {
class SslService : public RsaService {
class SslService : public DeviceUniqueDataService {
public:
SslService() : RsaService() { /* ... */ }
virtual ~SslService() { /* ... */ }
protected:
/* Actual commands. */
virtual Result ImportSslKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
virtual Result SslExpMod(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod);
public:
DEFINE_SERVICE_DISPATCH_TABLE {
MAKE_SERVICE_COMMAND_META(GetConfig),
MAKE_SERVICE_COMMAND_META(ExpMod),
MAKE_SERVICE_COMMAND_META(SetConfig),
MAKE_SERVICE_COMMAND_META(GenerateRandomBytes),
MAKE_SERVICE_COMMAND_META(IsDevelopment),
MAKE_SERVICE_COMMAND_META(SetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GetBootReason, hos::Version_3_0_0),
MAKE_SERVICE_COMMAND_META(GenerateAesKek),
MAKE_SERVICE_COMMAND_META(LoadAesKey),
MAKE_SERVICE_COMMAND_META(GenerateAesKey),
MAKE_SERVICE_COMMAND_META(DecryptAesKey),
MAKE_SERVICE_COMMAND_META(CryptAesCtr),
MAKE_SERVICE_COMMAND_META(ComputeCmac),
MAKE_SERVICE_COMMAND_META(AllocateAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(FreeAesKeyslot, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(GetAesKeyslotAvailableEvent, hos::Version_2_0_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKeyDeprecated, hos::Version_4_0_0, hos::Version_4_1_0),
MAKE_SERVICE_COMMAND_META(DecryptRsaPrivateKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(ImportSslKey, hos::Version_5_0_0),
MAKE_SERVICE_COMMAND_META(SslExpMod, hos::Version_5_0_0),
};
Result DecryptAndStoreSslClientCertKey(const sf::InPointerBuffer &src, AccessKey access_key, KeySource key_source);
Result ModularExponentiateWithSslClientCertKey(const sf::OutPointerBuffer &out, const sf::InPointerBuffer &base, const sf::InPointerBuffer &mod);
};
static_assert(spl::impl::IsISslInterface<SslService>);
}