sf: update ams.mitm for new format

This commit is contained in:
Michael Scire 2020-07-07 15:08:02 -07:00
parent 4485a46e53
commit e5a233efa2
27 changed files with 285 additions and 292 deletions

View file

@ -55,6 +55,7 @@
#include <stratosphere/map.hpp>
#include <stratosphere/ncm.hpp>
#include <stratosphere/nim.hpp>
#include <stratosphere/ns.hpp>
#include <stratosphere/patcher.hpp>
#include <stratosphere/pgl.hpp>
#include <stratosphere/psc.hpp>

View file

@ -0,0 +1,19 @@
/*
* 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/ns/impl/ns_i_async.hpp>

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 <vapours.hpp>
#include <stratosphere/err/err_error_context.hpp>
#include <stratosphere/sf.hpp>
namespace ams::ns::impl {
#define AMS_NS_I_ASYNC_RESULT_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Get, ()) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Cancel, ()) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetErrorContext, (::ams::sf::Out<::ams::err::ErrorContext> out))
AMS_SF_DEFINE_INTERFACE(IAsyncResult, AMS_NS_I_ASYNC_RESULT_INTERFACE_INFO)
}

View file

@ -164,7 +164,7 @@ namespace ams::sf::hipc {
}
template<typename Interface, typename ServiceImpl>
static constexpr inline std::shared_ptr<Service> MakeSharedMitm(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &client_info) {
static constexpr inline std::shared_ptr<Interface> MakeSharedMitm(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &client_info) {
return sf::MakeShared<Interface, ServiceImpl>(std::forward<std::shared_ptr<::Service>>(s), client_info);
}
@ -212,7 +212,8 @@ namespace ams::sf::hipc {
return ResultSuccess();
}
template<typename Interface, typename ServiceImpl, auto MakeShared = MakeSharedMitm<Interface, ServiceImpl>> requires (sf::IsMitmServiceObject<Interface>)
template<typename Interface, typename ServiceImpl, auto MakeShared = MakeSharedMitm<Interface, ServiceImpl>>
requires (sf::IsMitmServiceObject<Interface> && sf::IsMitmServiceImpl<ServiceImpl>)
Result RegisterMitmServer(sm::ServiceName service_name) {
/* Install mitm service. */
Handle port_handle;

View file

@ -180,7 +180,9 @@ namespace ams::sf::impl {
public: \
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION) \
private: \
template<typename S, typename T> requires (std::same_as<CLASSNAME, S> && !std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T>) \
template<typename S, typename T> \
requires ((std::same_as<CLASSNAME, S> && !std::same_as<CLASSNAME, T>&& Is##CLASSNAME<T>) && \
(::ams::sf::IsMitmServiceObject<S> == ::ams::sf::IsMitmServiceImpl<T>)) \
struct ImplGenerator { \
public: \
class ImplHolder : public S { \
@ -195,6 +197,9 @@ namespace ams::sf::impl {
} \
ALWAYS_INLINE T &GetImpl() { return this->impl; } \
ALWAYS_INLINE const T &GetImpl() const { return this->impl; } \
\
template<typename U = S> requires ::ams::sf::IsMitmServiceObject<S> && std::same_as<U, S> \
static ALWAYS_INLINE bool ShouldMitm(os::ProcessId p, ncm::ProgramId r) { return T::ShouldMitm(p, r); } \
private: \
CMD_MACRO(CLASSNAME, AMS_SF_IMPL_DECLARE_INTERFACE_FUNCTION_INVOKER) \
public: \

View file

@ -29,22 +29,26 @@ namespace ams::sf {
concept IsServiceObject = std::derived_from<T, IServiceObject>;
class IMitmServiceObject : public IServiceObject {
public:
virtual ~IMitmServiceObject() { /* ... */ }
};
class MitmServiceImplBase {
protected:
std::shared_ptr<::Service> forward_service;
sm::MitmProcessInfo client_info;
public:
IMitmServiceObject(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : forward_service(std::move(s)), client_info(c) { /* ... */ }
virtual ~IMitmServiceObject() { /* ... */ }
static bool ShouldMitm(os::ProcessId process_id, ncm::ProgramId program_id);
MitmServiceImplBase(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : forward_service(std::move(s)), client_info(c) { /* ... */ }
};
template<typename T>
concept IsMitmServiceObject = IsServiceObject<T> && std::derived_from<T, IMitmServiceObject>;
/* Utility. */
#define AMS_SF_MITM_SERVICE_OBJECT_CTOR(cls) cls(std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) : ::ams::sf::IMitmServiceObject(std::forward<std::shared_ptr<::Service>>(s), c)
template<typename T>
concept IsMitmServiceImpl = requires (std::shared_ptr<::Service> &&s, const sm::MitmProcessInfo &c) {
{ T(std::forward<std::shared_ptr<::Service>>(s), c) };
{ T::ShouldMitm(c) } -> std::same_as<bool>;
};
template<typename Interface, typename Impl, typename... Arguments> requires std::constructible_from<Impl, Arguments...>
constexpr ALWAYS_INLINE std::shared_ptr<typename Interface::ImplHolder<Impl>> MakeShared(Arguments &&... args) {

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