Revert "hoc-clk: add live vdd2, live boost clock and basic pwm dimming"

This reverts commit 15b7df8ef1.
This commit is contained in:
souldbminersmwc
2025-11-09 16:14:52 -05:00
parent 22ec140738
commit 21a3f953d7
3804 changed files with 435 additions and 570162 deletions

View File

@@ -1,128 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_service_for_bg_agent.hpp"
#include "sprofile_srv_service_for_system_process.hpp"
#include "sprofile_srv_service_getter.hpp"
namespace ams::sprofile::srv {
namespace {
constexpr const ProfileManager::SaveDataInfo SaveDataInfo = {
.id = 0x8000000000000220,
.mount_name = "sprof",
.size = 0x1C0000,
.journal_size = 0x80000,
.flags = fs::SaveDataFlags_KeepAfterResettingSystemSaveData,
};
constexpr const sm::ServiceName ServiceNameForBgAgent = sm::ServiceName::Encode("sprof:bg");
constexpr const sm::ServiceName ServiceNameForSystemProcess = sm::ServiceName::Encode("sprof:sp");
constexpr inline size_t BgAgentSessionCountMax = 2;
constexpr inline size_t SystemProcessSessionCountMax = 10;
constexpr inline size_t SessionCountMax = BgAgentSessionCountMax + SystemProcessSessionCountMax;
constexpr inline size_t PortCountMax = 2;
struct ServerManagerOptions {
static constexpr size_t PointerBufferSize = 0x0;
static constexpr size_t MaxDomains = SessionCountMax; /* NOTE: Official is 9 */
static constexpr size_t MaxDomainObjects = 16; /* NOTE: Official is 14 */
static constexpr bool CanDeferInvokeRequest = false;
static constexpr bool CanManageMitmServers = false;
};
using ServerManager = sf::hipc::ServerManager<PortCountMax, ServerManagerOptions, SessionCountMax>;
constinit util::TypedStorage<ProfileManager> g_profile_manager = {};
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForBgAgent, ServiceForBgAgent>> g_bg_service_object = {};
constinit util::TypedStorage<sf::UnmanagedServiceObject<ISprofileServiceForSystemProcess, ServiceForSystemProcess>> g_sp_service_object = {};
constinit util::TypedStorage<sf::UnmanagedServiceObject<IServiceGetter, ServiceGetter>> g_bg_service_getter = {};
constinit util::TypedStorage<sf::UnmanagedServiceObject<IServiceGetter, ServiceGetter>> g_sp_service_getter = {};
constinit util::TypedStorage<ServerManager> g_server_manager = {};
alignas(os::ThreadStackAlignment) constinit u8 g_ipc_thread_stack[0x3000];
constinit u8 g_heap[16_KB];
constinit os::ThreadType g_ipc_thread = {};
constinit lmem::HeapHandle g_heap_handle = nullptr;
constinit sf::ExpHeapMemoryResource g_sf_memory_resource;
void IpcServerThreadFunction(void *) {
/* Get the server manager. */
auto &server_manager = util::GetReference(g_server_manager);
/* Resume processing. */
server_manager.ResumeProcessing();
/* Loop processing. */
server_manager.LoopProcess();
}
}
void Initialize() {
/* Initialize heap. */
g_heap_handle = lmem::CreateExpHeap(g_heap, sizeof(g_heap), lmem::CreateOption_ThreadSafe);
/* Attach the memory resource to heap. */
g_sf_memory_resource.Attach(g_heap_handle);
/* Create the profile manager. */
util::ConstructAt(g_profile_manager, SaveDataInfo);
/* Process profile manager savedata. */
util::GetReference(g_profile_manager).InitializeSaveData();
/* Create the service objects. */
util::ConstructAt(g_bg_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
util::ConstructAt(g_sp_service_object, std::addressof(g_sf_memory_resource), util::GetPointer(g_profile_manager));
/* Create the service getters. */
util::ConstructAt(g_bg_service_getter, util::GetReference(g_bg_service_object).GetShared(), util::GetReference(g_sp_service_object).GetShared());
util::ConstructAt(g_sp_service_getter, nullptr, util::GetReference(g_sp_service_object).GetShared());
/* Create the server manager. */
util::ConstructAt(g_server_manager);
/* Create services. */
if (hos::GetVersion() >= hos::Version_14_0_0) {
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_bg_service_getter).GetShared(), ServiceNameForBgAgent, BgAgentSessionCountMax));
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_sp_service_getter).GetShared(), ServiceNameForSystemProcess, SystemProcessSessionCountMax));
} else {
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_bg_service_object).GetShared(), ServiceNameForBgAgent, BgAgentSessionCountMax));
R_ABORT_UNLESS(util::GetReference(g_server_manager).RegisterObjectForServer(util::GetReference(g_sp_service_object).GetShared(), ServiceNameForSystemProcess, SystemProcessSessionCountMax));
}
}
void StartIpcServer() {
/* Create the ipc server thread. */
R_ABORT_UNLESS(os::CreateThread(std::addressof(g_ipc_thread), IpcServerThreadFunction, nullptr, g_ipc_thread_stack, sizeof(g_ipc_thread_stack), AMS_GET_SYSTEM_THREAD_PRIORITY(sprofile, IpcServer)));
os::SetThreadNamePointer(std::addressof(g_ipc_thread), AMS_GET_SYSTEM_THREAD_NAME(sprofile, IpcServer));
/* Start the ipc server thread. */
os::StartThread(std::addressof(g_ipc_thread));
}
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
namespace ams::sprofile::srv {
Result ReadFile(const char *path, void *dst, size_t size, s64 offset) {
/* Open the file. */
fs::FileHandle file;
R_TRY_CATCH(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read)) {
R_CATCH_RETHROW(fs::ResultPathNotFound) /* It's okay if the file doesn't exist. */
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Read the file. */
size_t read_size;
R_TRY(fs::ReadFile(std::addressof(read_size), file, offset, dst, size));
/* Check the size was correct. */
AMS_ABORT_UNLESS(size == read_size);
R_SUCCEED();
}
Result WriteFile(const char *path, const void *src, size_t size) {
/* Create the file. */
R_TRY_CATCH(fs::CreateFile(path, size)) {
R_CATCH(fs::ResultPathAlreadyExists) { /* It's okay if the file already exists. */ }
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
/* Open the file. */
fs::FileHandle file;
R_ABORT_UNLESS(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write));
ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Set the file size. */
R_ABORT_UNLESS(fs::SetFileSize(file, size));
/* Write the file. */
R_RETURN(fs::WriteFile(file, 0, src, size, fs::WriteOption::Flush));
}
Result MoveFile(const char *src_path, const char *dst_path) {
/* Require that the source path is a file. */
{
fs::DirectoryEntryType type;
R_ABORT_UNLESS(fs::GetEntryType(std::addressof(type), src_path));
AMS_ABORT_UNLESS(type == fs::DirectoryEntryType_File);
}
/* Delete the destination file. */
R_TRY_CATCH(fs::DeleteFile(dst_path)) {
R_CATCH(fs::ResultPathNotFound) { /* It's okay if the dst path doesn't exist. */ }
} R_END_TRY_CATCH;
/* Move the source file to the destination file. */
R_TRY(fs::RenameFile(src_path, dst_path));
R_SUCCEED();
}
Result DeleteFile(const char *path) {
R_TRY_CATCH(fs::DeleteFile(path)) {
R_CATCH(fs::ResultPathNotFound) { /* It's okay if the file doesn't exist. */ }
} R_END_TRY_CATCH;
R_SUCCEED();
}
Result EnsureDirectory(const char *path) {
R_TRY_CATCH(fs::CreateDirectory(path)) {
R_CATCH(fs::ResultPathAlreadyExists) { /* It's okay if the directory already exists. */ }
} R_END_TRY_CATCH;
R_SUCCEED();
}
}

View File

@@ -1,28 +0,0 @@
/*
* Copyright (c) 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::sprofile::srv {
Result ReadFile(const char *path, void *dst, size_t size, s64 offset);
Result WriteFile(const char *path, const void *src, size_t size);
Result MoveFile(const char *src_path, const char *dst_path);
Result DeleteFile(const char *path);
Result EnsureDirectory(const char *path);
}

View File

@@ -1,24 +0,0 @@
/*
* Copyright (c) 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>
#define AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ()) \
AMS_SF_METHOD_INFO(C, H, 2001, Result, GetRaw, (sf::Out<u8> out_type, sf::Out<u64> out_value, sprofile::Identifier profile, sprofile::Identifier key), (out_type, out_value, profile, key))
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileControllerForDebug, AMS_SPROFILE_I_PROFILE_CONTROLLER_FOR_DEBUG_INTERFACE_INFO, 0xA8C14F64)

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_types.hpp"
#define AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, ImportProfile, (const sprofile::srv::ProfileDataForImportData &import), (import)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Commit, (), ()) \
AMS_SF_METHOD_INFO(C, H, 2, Result, ImportMetadata, (const sprofile::srv::ProfileMetadataForImportMetadata &import), (import)) \
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileImporter, AMS_SPROFILE_I_PROFILE_IMPORTER_INTERFACE_INFO, 0x1629C4E6)

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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>
#define AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetSigned64, (sf::Out<s64> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetUnsigned64, (sf::Out<u64> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetSigned32, (sf::Out<s32> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetUnsigned32, (sf::Out<u32> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, GetByte, (sf::Out<u8> out, sprofile::Identifier profile, sprofile::Identifier key), (out, profile, key))
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileReader, AMS_SPROFILE_I_PROFILE_READER_INTERFACE_INFO, 0x97090D4D)

View File

@@ -1,24 +0,0 @@
/*
* Copyright (c) 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>
#define AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Listen, (sprofile::Identifier profile), (profile)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Unlisten, (sprofile::Identifier profile), (profile)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, GetEventHandle, (ams::sf::OutCopyHandle out), (out))
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IProfileUpdateObserver, AMS_SPROFILE_I_PROFILE_UPDATE_OBSERVER_INTERFACE_INFO, 0xB52A765C)

View File

@@ -1,26 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_importer.hpp"
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileImporter, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 200, Result, GetImportableProfileUrls, (sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg), (out_count, out, arg)) \
AMS_SF_METHOD_INFO(C, H, 201, Result, IsUpdateNeeded, (sf::Out<bool> out, sprofile::Identifier revision_key), (out, revision_key)) \
AMS_SF_METHOD_INFO(C, H, 2000, Result, Reset, (), ())
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, ISprofileServiceForBgAgent, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_BG_AGENT_INTERFACE_INFO, 0xCCD828EC)

View File

@@ -1,27 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_reader.hpp"
#include "sprofile_srv_i_profile_update_observer.hpp"
#include "sprofile_srv_i_profile_controller_for_debug.hpp"
#define AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 100, Result, OpenProfileReader, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 101, Result, OpenProfileUpdateObserver, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 900, Result, OpenProfileControllerForDebug, (sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out), (out))
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, ISprofileServiceForSystemProcess, AMS_SPROFILE_I_SPROFILE_SERVICE_FOR_SYSTEM_PROCESS_INTERFACE_INFO, 0x919612FB)

View File

@@ -1,25 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_service_for_system_process.hpp"
#include "sprofile_srv_i_service_for_bg_agent.hpp"
#define AMS_SPROFILE_I_SERVICE_GETTER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GetServiceForSystemProcess, (sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetServiceForBgAgent, (sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out), (out))
AMS_SF_DEFINE_INTERFACE(ams::sprofile::srv, IServiceGetter, AMS_SPROFILE_I_SERVICE_GETTER_INTERFACE_INFO, 0x2CFB8417)

View File

@@ -1,30 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_profile_controller_for_debug_impl.hpp"
namespace ams::sprofile::srv {
Result ProfileControllerForDebugImpl::Reset() {
R_RETURN(m_manager->ResetSaveData());
}
Result ProfileControllerForDebugImpl::GetRaw(sf::Out<u8> out_type, sf::Out<u64> out_value, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetRaw(out_type.GetPointer(), out_value.GetPointer(), profile, key));
}
}

View File

@@ -1,35 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_controller_for_debug.hpp"
namespace ams::sprofile::srv {
class ProfileManager;
class ProfileControllerForDebugImpl {
private:
ProfileManager *m_manager;
public:
ProfileControllerForDebugImpl(ProfileManager *manager) : m_manager(manager) { /* ... */ }
public:
Result Reset();
Result GetRaw(sf::Out<u8> out_type, sf::Out<u64> out_value, sprofile::Identifier profile, sprofile::Identifier key);
};
static_assert(IsIProfileControllerForDebug<ProfileControllerForDebugImpl>);
}

View File

@@ -1,167 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_types.hpp"
namespace ams::sprofile::srv {
class ProfileImporter {
private:
struct ImportingProfile {
Identifier identifier_0;
Identifier identifier_1;
bool is_new_import;
};
private:
bool m_committed;
bool m_imported_metadata;
int m_importing_count;
util::optional<ProfileMetadata> m_metadata;
ImportingProfile m_importing_profiles[50];
util::BitFlagSet<50> m_is_profile_importable;
Identifier m_revision_key;
public:
ProfileImporter(const util::optional<ProfileMetadata> &meta) : m_committed(false), m_imported_metadata(false), m_importing_count(0), m_metadata(util::nullopt), m_is_profile_importable(), m_revision_key() {
if (meta.has_value()) {
m_metadata = *meta;
}
}
public:
bool HasProfile(Identifier id0, Identifier id1) {
/* Require that we have metadata. */
if (m_metadata.has_value()) {
for (auto i = 0u; i < std::min<size_t>(m_metadata->num_entries, util::size(m_metadata->entries)); ++i) {
const auto &entry = m_metadata->entries[i];
if (entry.identifier_0 == id0 && entry.identifier_1 == id1) {
return true;
}
}
}
/* We don't have the desired profile. */
return false;
}
bool CanImportMetadata() {
/* We can only import metadata if we haven't already imported metadata. */
return !m_imported_metadata;
}
void ImportMetadata(const ProfileMetadata &meta) {
/* Set that we've imported metadata. */
m_imported_metadata = true;
/* Import the service revision key. */
m_revision_key = meta.revision_key;
/* Set importing count. */
m_importing_count = static_cast<int>(std::min<size_t>(meta.num_entries, util::size(meta.entries)));
/* Set all profiles as importable. */
for (auto i = 0; i < m_importing_count; ++i) {
m_is_profile_importable[i] = true;
}
/* Determine import status for all profiles. */
for (auto i = 0; i < m_importing_count; ++i) {
const auto &import_entry = meta.entries[i];
const bool is_new_import = !this->HasProfile(import_entry.identifier_0, import_entry.identifier_1);
m_importing_profiles[i] = {
.identifier_0 = import_entry.identifier_0,
.identifier_1 = import_entry.identifier_1,
.is_new_import = is_new_import,
};
m_is_profile_importable[i] = is_new_import;
}
}
bool CanImportProfile(Identifier profile) {
/* Require that we imported metadata. */
if (m_imported_metadata) {
/* Find the specified profile. */
for (auto i = 0; i < m_importing_count; ++i) {
if (m_importing_profiles[i].identifier_0 == profile) {
/* Require the profile be importable. */
return m_is_profile_importable[i];
}
}
}
/* We can't import the desired profile. */
return false;
}
void OnImportProfile(Identifier profile) {
/* Set the profile as not importable (as it's imported). */
for (auto i = 0; i < m_importing_count; ++i) {
if (m_importing_profiles[i].identifier_0 == profile) {
m_is_profile_importable[i] = false;
break;
}
}
}
bool CanCommit() {
/* We can't commit if we've already committed. */
if (m_committed) {
return false;
}
/* We need metadata in order to commit. */
if (!m_imported_metadata) {
return false;
}
/* We need to have imported everything we intended to import. */
return m_is_profile_importable.IsAllOff();
}
int GetImportingCount() const { return m_importing_count; }
const ImportingProfile &GetImportingProfile(int i) const { return m_importing_profiles[i]; }
Identifier GetRevisionKey() const { return m_revision_key; }
Result CleanupOrphanedProfiles(auto cleanup_impl) const {
/* Cleanup any orphaned profiles in our metadata. */
if (m_metadata.has_value()) {
for (auto i = 0u; i < std::min<size_t>(m_metadata->num_entries, util::size(m_metadata->entries)); ++i) {
const auto &entry = m_metadata->entries[i];
if (!this->IsImportingProfile(entry.identifier_0)) {
R_TRY(cleanup_impl(entry.identifier_0));
}
}
}
R_SUCCEED();
}
private:
bool IsImportingProfile(Identifier profile) const {
/* Check if we're importing the desired profile. */
for (auto i = 0; i < m_importing_count; ++i) {
if (m_importing_profiles[i].identifier_0 == profile) {
return true;
}
}
/* We're not importing the desired profile. */
return false;
}
};
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_profile_importer_impl.hpp"
namespace ams::sprofile::srv {
Result ProfileImporterImpl::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) {
R_RETURN(m_manager->ImportProfile(import));
}
Result ProfileImporterImpl::Commit() {
R_RETURN(m_manager->Commit());
}
Result ProfileImporterImpl::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) {
R_RETURN(m_manager->ImportMetadata(import));
}
}

View File

@@ -1,40 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_importer.hpp"
namespace ams::sprofile::srv {
class ProfileManager;
class ProfileImporterImpl {
private:
ProfileManager *m_manager;
public:
ProfileImporterImpl(ProfileManager *manager) : m_manager(manager) { /* ... */ }
~ProfileImporterImpl() {
m_manager->CloseProfileImporter();
}
public:
Result ImportProfile(const sprofile::srv::ProfileDataForImportData &import);
Result Commit();
Result ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import);
};
static_assert(IsIProfileImporter<ProfileImporterImpl>);
}

View File

@@ -1,558 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_fs_utils.hpp"
namespace ams::sprofile::srv {
namespace {
constexpr const char PrimaryDirectoryName[] = "primary";
constexpr const char TemporaryDirectoryName[] = "temp";
Result CreateSaveData(const ProfileManager::SaveDataInfo &save_data_info) {
R_TRY_CATCH(fs::CreateSystemSaveData(save_data_info.id, save_data_info.size, save_data_info.journal_size, save_data_info.flags)) {
R_CATCH(fs::ResultPathAlreadyExists) { /* Nintendo accepts already-existing savedata here. */ }
} R_END_TRY_CATCH;
R_SUCCEED();
}
void SafePrint(char *dst, size_t dst_size, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
void SafePrint(char *dst, size_t dst_size, const char *fmt, ...) {
std::va_list vl;
va_start(vl, fmt);
const size_t len = util::TVSNPrintf(dst, dst_size, fmt, vl);
va_end(vl);
AMS_ABORT_UNLESS(len < dst_size);
}
void CreateMetadataPathImpl(char *dst, size_t dst_size, const char *mount, const char *dir) {
SafePrint(dst, dst_size, "%s:/%s/metadata", mount, dir);
}
void CreatePrimaryMetadataPath(char *dst, size_t dst_size, const char *mount) {
CreateMetadataPathImpl(dst, dst_size, mount, PrimaryDirectoryName);
}
void CreateTemporaryMetadataPath(char *dst, size_t dst_size, const char *mount) {
CreateMetadataPathImpl(dst, dst_size, mount, TemporaryDirectoryName);
}
void CreateProfilePathImpl(char *dst, size_t dst_size, const char *mount, const char *dir, const Identifier &id) {
SafePrint(dst, dst_size, "%s:/%s/profiles/%02x%02x%02x%02x%02x%02x%02x", mount, dir, id.data[0], id.data[1], id.data[2], id.data[3], id.data[4], id.data[5], id.data[6]);
}
void CreatePrimaryProfilePath(char *dst, size_t dst_size, const char *mount, const Identifier &id) {
CreateProfilePathImpl(dst, dst_size, mount, PrimaryDirectoryName, id);
}
void CreateTemporaryProfilePath(char *dst, size_t dst_size, const char *mount, const Identifier &id) {
CreateProfilePathImpl(dst, dst_size, mount, TemporaryDirectoryName, id);
}
void CreateDirectoryPathImpl(char *dst, size_t dst_size, const char *mount, const char *dir) {
SafePrint(dst, dst_size, "%s:/%s", mount, dir);
}
void CreatePrimaryDirectoryPath(char *dst, size_t dst_size, const char *mount) {
CreateDirectoryPathImpl(dst, dst_size, mount, PrimaryDirectoryName);
}
void CreateTemporaryDirectoryPath(char *dst, size_t dst_size, const char *mount) {
CreateDirectoryPathImpl(dst, dst_size, mount, TemporaryDirectoryName);
}
void CreateProfileDirectoryPathImpl(char *dst, size_t dst_size, const char *mount, const char *dir) {
SafePrint(dst, dst_size, "%s:/%s/profiles", mount, dir);
}
void CreatePrimaryProfileDirectoryPath(char *dst, size_t dst_size, const char *mount) {
CreateProfileDirectoryPathImpl(dst, dst_size, mount, PrimaryDirectoryName);
}
void CreateTemporaryProfileDirectoryPath(char *dst, size_t dst_size, const char *mount) {
CreateProfileDirectoryPathImpl(dst, dst_size, mount, TemporaryDirectoryName);
}
}
ProfileManager::ProfileManager(const SaveDataInfo &save_data_info)
: m_save_data_info(save_data_info), m_save_file_mounted(false), m_profile_importer(util::nullopt),
m_profile_metadata(util::nullopt), m_service_profile(util::nullopt), m_update_observer_manager()
{
/* ... */
}
void ProfileManager::InitializeSaveData() {
/* Acquire locks. */
std::scoped_lock lk1(m_general_mutex);
std::scoped_lock lk2(m_fs_mutex);
/* Ensure the savedata exists. */
if (R_SUCCEEDED(CreateSaveData(m_save_data_info))) {
m_save_file_mounted = R_SUCCEEDED(fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id));
}
}
Result ProfileManager::ResetSaveData() {
/* Acquire locks. */
std::scoped_lock lk1(m_service_profile_mutex);
std::scoped_lock lk2(m_profile_metadata_mutex);
std::scoped_lock lk3(m_general_mutex);
std::scoped_lock lk4(m_fs_mutex);
/* Unmount save file. */
fs::Unmount(m_save_data_info.mount_name);
m_save_file_mounted = false;
/* Delete save file. */
R_TRY(fs::DeleteSystemSaveData(fs::SaveDataSpaceId::System, m_save_data_info.id, fs::InvalidUserId));
/* Unload profile. */
m_profile_metadata = util::nullopt;
m_service_profile = util::nullopt;
/* Create the save data. */
R_TRY(CreateSaveData(m_save_data_info));
/* Try to mount the save file. */
const auto result = fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id);
m_save_file_mounted = R_SUCCEEDED(result);
R_RETURN(result);
}
Result ProfileManager::OpenProfileImporter() {
/* Acquire locks. */
std::scoped_lock lk1(m_profile_metadata_mutex);
std::scoped_lock lk2(m_profile_importer_mutex);
std::scoped_lock lk3(m_general_mutex);
/* Check that we don't already have an importer. */
R_UNLESS(!m_profile_importer.has_value(), sprofile::ResultInvalidState());
/* Try to load profile metadata. NOTE: result is not checked, it is okay if this fails. */
this->LoadPrimaryMetadataImpl();
/* Create importer. */
m_profile_importer.emplace(m_profile_metadata);
R_SUCCEED();
}
void ProfileManager::CloseProfileImporterImpl() {
/* Check pre-conditions. */
AMS_ASSERT(m_profile_importer_mutex.IsLockedByCurrentThread());
AMS_ASSERT(m_general_mutex.IsLockedByCurrentThread());
AMS_ASSERT(m_fs_mutex.IsLockedByCurrentThread());
if (m_profile_importer.has_value()) {
/* Unmount save file. */
fs::Unmount(m_save_data_info.mount_name);
m_save_file_mounted = false;
/* Re-mount save file. */
R_ABORT_UNLESS(fs::MountSystemSaveData(m_save_data_info.mount_name, m_save_data_info.id));
m_save_file_mounted = true;
/* Reset our importer. */
m_profile_importer = util::nullopt;
}
}
void ProfileManager::CloseProfileImporter() {
/* Acquire locks. */
std::scoped_lock lk1(m_profile_importer_mutex);
std::scoped_lock lk2(m_general_mutex);
std::scoped_lock lk3(m_fs_mutex);
/* Close our importer. */
this->CloseProfileImporterImpl();
}
Result ProfileManager::ImportProfile(const sprofile::srv::ProfileDataForImportData &import) {
/* Acquire locks. */
std::scoped_lock lk1(m_profile_importer_mutex);
std::scoped_lock lk2(m_fs_mutex);
/* Check that we have an importer. */
R_UNLESS(m_profile_importer.has_value(), sprofile::ResultInvalidState());
/* Check that the metadata we're importing is a valid version. */
R_UNLESS(IsValidProfileFormatVersion(import.header.version), sprofile::ResultInvalidDataVersion());
/* Check that the metadata we're importing has a valid hash. */
{
crypto::Md5Generator md5;
md5.Initialize();
md5.Update(std::addressof(import.header), sizeof(import.header));
md5.Update(std::addressof(import.data), sizeof(import.data) - sizeof(import.data.entries[0]) * (util::size(import.data.entries) - std::min<size_t>(import.data.num_entries, util::size(import.data.entries))));
u8 hash[crypto::Md5Generator::HashSize];
md5.GetHash(hash, sizeof(hash));
R_UNLESS(crypto::IsSameBytes(hash, import.hash, sizeof(hash)), sprofile::ResultInvalidDataHash());
}
/* Succeed if we already have the profile. */
R_SUCCEED_IF(m_profile_importer->HasProfile(import.header.identifier_0, import.header.identifier_1));
/* Check that we're importing the profile. */
R_UNLESS(m_profile_importer->CanImportProfile(import.header.identifier_0), sprofile::ResultInvalidState());
/* Create temporary directories. */
R_TRY(this->EnsureTemporaryDirectories());
/* Create profile. */
char path[0x30];
CreateTemporaryProfilePath(path, sizeof(path), m_save_data_info.mount_name, import.header.identifier_0);
R_TRY(WriteFile(path, std::addressof(import.data), sizeof(import.data)));
/* Set profile imported. */
m_profile_importer->OnImportProfile(import.header.identifier_0);
R_SUCCEED();
}
Result ProfileManager::Commit() {
/* Acquire locks. */
std::scoped_lock lk1(m_service_profile_mutex);
std::scoped_lock lk2(m_profile_metadata_mutex);
std::scoped_lock lk3(m_profile_importer_mutex);
std::scoped_lock lk4(m_general_mutex);
std::scoped_lock lk5(m_fs_mutex);
/* Check that we have an importer. */
R_UNLESS(m_profile_importer.has_value(), sprofile::ResultInvalidState());
/* Commit, and if we fail remount our save. */
{
/* If we fail, close our importer. */
ON_RESULT_FAILURE { this->CloseProfileImporterImpl(); };
/* Check that we can commit the importer. */
R_UNLESS(m_profile_importer->CanCommit(), sprofile::ResultInvalidState());
/* Commit newly imported profiles. */
R_TRY(this->CommitImportedProfiles());
/* Cleanup orphaned profiles. */
R_TRY(this->CleanupOrphanedProfiles());
/* Commit the save file. */
R_TRY(fs::CommitSaveData(m_save_data_info.mount_name));
}
/* NOTE: Here nintendo generates an "sprofile_update_profile" sreport with the new and old revision keys. */
/* Handle tasks for when we've committed (including notifying update observers). */
this->OnCommitted();
R_SUCCEED();
}
Result ProfileManager::ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &import) {
/* Acquire locks. */
std::scoped_lock lk1(m_profile_importer_mutex);
std::scoped_lock lk2(m_fs_mutex);
/* Check that we can import metadata. */
R_UNLESS(m_profile_importer.has_value(), sprofile::ResultInvalidState());
R_UNLESS(m_profile_importer->CanImportMetadata(), sprofile::ResultInvalidState());
/* Check that the metadata we're importing is a valid version. */
R_UNLESS(IsValidProfileFormatVersion(import.header.version), sprofile::ResultInvalidMetadataVersion());
/* Check that the metadata we're importing has a valid hash. */
{
crypto::Md5Generator md5;
md5.Initialize();
md5.Update(std::addressof(import.header), sizeof(import.header));
md5.Update(std::addressof(import.metadata), sizeof(import.metadata));
md5.Update(std::addressof(import.profile_urls), sizeof(import.profile_urls[0]) * std::min<size_t>(import.metadata.num_entries, util::size(import.metadata.entries)));
u8 hash[crypto::Md5Generator::HashSize];
md5.GetHash(hash, sizeof(hash));
R_UNLESS(crypto::IsSameBytes(hash, import.hash, sizeof(hash)), sprofile::ResultInvalidMetadataHash());
}
/* Create temporary directories. */
R_TRY(this->EnsureTemporaryDirectories());
/* Create metadata. */
char path[0x30];
CreateTemporaryMetadataPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(WriteFile(path, std::addressof(import.metadata), sizeof(import.metadata)));
/* Import the metadata. */
m_profile_importer->ImportMetadata(import.metadata);
R_SUCCEED();
}
Result ProfileManager::LoadPrimaryMetadataImpl() {
/* Check pre-conditions. */
AMS_ASSERT(m_profile_metadata_mutex.IsLockedByCurrentThread());
AMS_ASSERT(m_general_mutex.IsLockedByCurrentThread());
/* If we don't have metadata, load it. */
if (!m_profile_metadata.has_value()) {
/* Emplace our metadata. */
m_profile_metadata.emplace();
ON_RESULT_FAILURE { m_profile_metadata = util::nullopt; };
/* Read profile metadata. */
char path[0x30];
CreatePrimaryMetadataPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(ReadFile(path, std::addressof(*m_profile_metadata), sizeof(*m_profile_metadata), 0));
}
/* We now have loaded metadata. */
R_SUCCEED();
}
Result ProfileManager::LoadPrimaryMetadata(ProfileMetadata *out) {
/* Acquire locks. */
std::scoped_lock lk1(m_profile_metadata_mutex);
std::scoped_lock lk2(m_general_mutex);
/* Load our metadata. */
R_TRY(this->LoadPrimaryMetadataImpl());
/* Set the output. */
*out = *m_profile_metadata;
R_SUCCEED();
}
Result ProfileManager::LoadProfile(Identifier profile) {
/* Check if we already have the profile. */
if (m_service_profile.has_value()) {
R_SUCCEED_IF(m_service_profile->name == profile);
}
/* If we fail past this point, we want to have no profile. */
auto prof_guard = SCOPE_GUARD { m_service_profile = util::nullopt; };
/* Create profile path. */
char path[0x30];
CreatePrimaryProfilePath(path, sizeof(path), m_save_data_info.mount_name, profile);
/* Load the profile. */
m_service_profile = {};
R_TRY(ReadFile(path, std::addressof(m_service_profile->data), sizeof(m_service_profile->data), 0));
/* We succeeded. */
prof_guard.Cancel();
R_SUCCEED();
}
Result ProfileManager::GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key) {
/* Acquire locks. */
std::scoped_lock lk1(m_service_profile_mutex);
std::scoped_lock lk2(m_general_mutex);
/* Load the desired profile. */
if (R_SUCCEEDED(this->LoadProfile(profile))) {
/* Find the specified key. */
for (auto i = 0u; i < std::min<size_t>(m_service_profile->data.num_entries, util::size(m_service_profile->data.entries)); ++i) {
if (m_service_profile->data.entries[i].key == key) {
*out = m_service_profile->data.entries[i];
R_SUCCEED();
}
}
}
R_THROW(sprofile::ResultKeyNotFound());
}
Result ProfileManager::GetSigned64(s64 *out, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Check the type. */
R_UNLESS(entry.type == ValueType_S64, sprofile::ResultInvalidDataType());
/* Set the output value. */
*out = entry.value_s64;
R_SUCCEED();
}
Result ProfileManager::GetUnsigned64(u64 *out, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Check the type. */
R_UNLESS(entry.type == ValueType_U64, sprofile::ResultInvalidDataType());
/* Set the output value. */
*out = entry.value_u64;
R_SUCCEED();
}
Result ProfileManager::GetSigned32(s32 *out, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Check the type. */
R_UNLESS(entry.type == ValueType_S32, sprofile::ResultInvalidDataType());
/* Set the output value. */
*out = entry.value_s32;
R_SUCCEED();
}
Result ProfileManager::GetUnsigned32(u32 *out, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Check the type. */
R_UNLESS(entry.type == ValueType_U32, sprofile::ResultInvalidDataType());
/* Set the output value. */
*out = entry.value_u32;
R_SUCCEED();
}
Result ProfileManager::GetByte(u8 *out, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Check the type. */
R_UNLESS(entry.type == ValueType_Byte, sprofile::ResultInvalidDataType());
/* Set the output value. */
*out = entry.value_u8;
R_SUCCEED();
}
Result ProfileManager::GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key) {
/* Get the data entry. */
ProfileDataEntry entry;
R_TRY(this->GetDataEntry(std::addressof(entry), profile, key));
/* Set the output type and value. */
*out_type = entry.type;
*out_value = entry.value_u64;
R_SUCCEED();
}
Result ProfileManager::CommitImportedProfiles() {
/* Ensure primary directories. */
R_TRY(this->EnsurePrimaryDirectories());
/* Declare re-usable paths. */
char tmp_path[0x30];
char pri_path[0x30];
/* Move the metadata. */
{
CreateTemporaryMetadataPath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name);
CreatePrimaryMetadataPath(pri_path, sizeof(pri_path), m_save_data_info.mount_name);
R_TRY(MoveFile(tmp_path, pri_path));
}
/* Move all newly imported profiles. */
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
const auto &profile = m_profile_importer->GetImportingProfile(i);
if (profile.is_new_import) {
CreateTemporaryProfilePath(tmp_path, sizeof(tmp_path), m_save_data_info.mount_name, profile.identifier_0);
CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile.identifier_0);
R_TRY(MoveFile(tmp_path, pri_path));
}
}
R_SUCCEED();
}
Result ProfileManager::CleanupOrphanedProfiles() {
/* Check pre-conditions. */
AMS_ASSERT(m_profile_importer.has_value());
/* Declare re-usable path. */
char pri_path[0x30];
/* Cleanup the profiles. */
R_RETURN(m_profile_importer->CleanupOrphanedProfiles([&](Identifier profile) ALWAYS_INLINE_LAMBDA -> Result {
CreatePrimaryProfilePath(pri_path, sizeof(pri_path), m_save_data_info.mount_name, profile);
R_RETURN(DeleteFile(pri_path));
}));
}
void ProfileManager::OnCommitted() {
/* TODO: Here, Nintendo sets the erpt ServiceProfileRevisionKey to the current revision key. */
/* If we need to, invalidate the loaded service profile. */
if (m_service_profile.has_value()) {
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
if (m_service_profile->name == m_profile_importer->GetImportingProfile(i).identifier_0) {
m_service_profile = util::nullopt;
break;
}
}
}
/* Reset profile metadata. */
m_profile_metadata = util::nullopt;
/* Invoke any listeners. */
for (auto i = 0; i < m_profile_importer->GetImportingCount(); ++i) {
const auto &profile = m_profile_importer->GetImportingProfile(i);
if (profile.is_new_import) {
m_update_observer_manager.OnUpdate(profile.identifier_0);
}
}
/* Reset profile importer. */
m_profile_importer = util::nullopt;
}
Result ProfileManager::EnsurePrimaryDirectories() {
/* Ensure the primary directories. */
char path[0x30];
CreatePrimaryDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(EnsureDirectory(path));
CreatePrimaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(EnsureDirectory(path));
R_SUCCEED();
}
Result ProfileManager::EnsureTemporaryDirectories() {
/* Ensure the temporary directories. */
char path[0x30];
CreateTemporaryDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(EnsureDirectory(path));
CreateTemporaryProfileDirectoryPath(path, sizeof(path), m_save_data_info.mount_name);
R_TRY(EnsureDirectory(path));
R_SUCCEED();
}
}

View File

@@ -1,87 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_types.hpp"
#include "sprofile_srv_profile_update_observer_impl.hpp"
#include "sprofile_srv_profile_importer.hpp"
namespace ams::sprofile::srv {
class ProfileManager {
public:
struct SaveDataInfo {
u64 id;
const char *mount_name;
size_t size;
size_t journal_size;
u32 flags;
};
private:
private:
os::SdkMutex m_general_mutex{};
os::SdkMutex m_fs_mutex{};
SaveDataInfo m_save_data_info;
bool m_save_file_mounted;
util::optional<ProfileImporter> m_profile_importer;
os::SdkMutex m_profile_importer_mutex{};
util::optional<ProfileMetadata> m_profile_metadata;
os::SdkMutex m_profile_metadata_mutex{};
util::optional<ServiceProfile> m_service_profile;
os::SdkMutex m_service_profile_mutex{};
ProfileUpdateObserverManager m_update_observer_manager;
public:
ProfileManager(const SaveDataInfo &save_data_info);
public:
void InitializeSaveData();
Result ResetSaveData();
Result OpenProfileImporter();
void CloseProfileImporter();
Result ImportProfile(const sprofile::srv::ProfileDataForImportData &data);
Result Commit();
Result ImportMetadata(const sprofile::srv::ProfileMetadataForImportMetadata &data);
Result LoadPrimaryMetadata(ProfileMetadata *out);
Result GetSigned64(s64 *out, Identifier profile, Identifier key);
Result GetUnsigned64(u64 *out, Identifier profile, Identifier key);
Result GetSigned32(s32 *out, Identifier profile, Identifier key);
Result GetUnsigned32(u32 *out, Identifier profile, Identifier key);
Result GetByte(u8 *out, Identifier profile, Identifier key);
Result GetRaw(u8 *out_type, u64 *out_value, Identifier profile, Identifier key);
ProfileUpdateObserverManager &GetUpdateObserverManager() { return m_update_observer_manager; }
private:
Result CommitImportedProfiles();
Result CleanupOrphanedProfiles();
Result LoadPrimaryMetadataImpl();
void CloseProfileImporterImpl();
void OnCommitted();
Result GetDataEntry(ProfileDataEntry *out, Identifier profile, Identifier key);
Result LoadProfile(Identifier profile);
Result EnsurePrimaryDirectories();
Result EnsureTemporaryDirectories();
};
}

View File

@@ -1,42 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_profile_reader_impl.hpp"
namespace ams::sprofile::srv {
Result ProfileReaderImpl::GetSigned64(sf::Out<s64> out, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetSigned64(out.GetPointer(), profile, key));
}
Result ProfileReaderImpl::GetUnsigned64(sf::Out<u64> out, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetUnsigned64(out.GetPointer(), profile, key));
}
Result ProfileReaderImpl::GetSigned32(sf::Out<s32> out, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetSigned32(out.GetPointer(), profile, key));
}
Result ProfileReaderImpl::GetUnsigned32(sf::Out<u32> out, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetUnsigned32(out.GetPointer(), profile, key));
}
Result ProfileReaderImpl::GetByte(sf::Out<u8> out, sprofile::Identifier profile, sprofile::Identifier key) {
R_RETURN(m_manager->GetByte(out.GetPointer(), profile, key));
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_reader.hpp"
namespace ams::sprofile::srv {
class ProfileManager;
class ProfileReaderImpl {
private:
ProfileManager *m_manager;
public:
ProfileReaderImpl(ProfileManager *manager) : m_manager(manager) { /* ... */ }
public:
Result GetSigned64(sf::Out<s64> out, sprofile::Identifier profile, sprofile::Identifier key);
Result GetUnsigned64(sf::Out<u64> out, sprofile::Identifier profile, sprofile::Identifier key);
Result GetSigned32(sf::Out<s32> out, sprofile::Identifier profile, sprofile::Identifier key);
Result GetUnsigned32(sf::Out<u32> out, sprofile::Identifier profile, sprofile::Identifier key);
Result GetByte(sf::Out<u8> out, sprofile::Identifier profile, sprofile::Identifier key);
};
static_assert(IsIProfileReader<ProfileReaderImpl>);
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_profile_update_observer_impl.hpp"
namespace ams::sprofile::srv {
namespace {
class AutoUnregisterObserver : public ProfileUpdateObserverImpl {
private:
ProfileUpdateObserverManager *m_manager;
public:
AutoUnregisterObserver(ProfileUpdateObserverManager *manager) : m_manager(manager) { /* ... */ }
virtual ~AutoUnregisterObserver() { m_manager->CloseObserver(this); }
};
static_assert(sprofile::srv::IsIProfileUpdateObserver<AutoUnregisterObserver>);
}
Result ProfileUpdateObserverManager::OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> &out, MemoryResource *memory_resource) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Check that we can allocate. */
R_UNLESS(m_observer_count < MaxObservers, sprofile::ResultMaxObservers());
/* Allocate an object. */
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileUpdateObserver, AutoUnregisterObserver>(memory_resource, this);
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
/* Register the observer. */
m_observers[m_observer_count++] = std::addressof(obj.GetImpl());
/* Return the object. */
*out = std::move(obj);
R_SUCCEED();
}
void ProfileUpdateObserverManager::CloseObserver(ProfileUpdateObserverImpl *observer) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Find the observer. */
int index = -1;
for (auto i = 0; i < m_observer_count; ++i) {
if (m_observers[i] == observer) {
index = i;
break;
}
}
AMS_ABORT_UNLESS(index != -1);
/* Remove from our list. */
m_observers[index] = m_observers[--m_observer_count];
/* Sanity check. */
AMS_ABORT_UNLESS(m_observer_count >= 0);
}
}

View File

@@ -1,105 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_profile_update_observer.hpp"
namespace ams::sprofile::srv {
class ProfileUpdateObserverImpl {
public:
static constexpr auto MaxProfiles = 4;
private:
os::SystemEvent m_event;
Identifier m_profiles[MaxProfiles];
int m_profile_count;
os::SdkMutex m_mutex;
public:
ProfileUpdateObserverImpl() : m_event(os::EventClearMode_ManualClear, true), m_profile_count(0), m_mutex() { /* ... */ }
virtual ~ProfileUpdateObserverImpl() { /* ... */ }
public:
os::SystemEvent &GetEvent() { return m_event; }
const os::SystemEvent &GetEvent() const { return m_event; }
public:
Result Listen(Identifier profile) {
/* Lock ourselves. */
std::scoped_lock lk(m_mutex);
/* Check if we can listen. */
R_UNLESS(m_profile_count < MaxProfiles, sprofile::ResultMaxListeners());
/* Check if we're already listening. */
for (auto i = 0; i < m_profile_count; ++i) {
R_UNLESS(m_profiles[i] != profile, sprofile::ResultAlreadyListening());
}
/* Add the profile. */
m_profiles[m_profile_count++] = profile;
R_SUCCEED();
}
Result Unlisten(Identifier profile) {
/* Check that we're listening. */
for (auto i = 0; i < m_profile_count; ++i) {
if (m_profiles[i] == profile) {
m_profiles[i] = m_profiles[--m_profile_count];
AMS_ABORT_UNLESS(m_profile_count >= 0);
R_SUCCEED();
}
}
R_THROW(sprofile::ResultNotListening());
}
Result GetEventHandle(sf::OutCopyHandle out) {
out.SetValue(m_event.GetReadableHandle(), false);
R_SUCCEED();
}
public:
void OnUpdate(Identifier profile) {
for (auto i = 0; i < m_profile_count; ++i) {
if (m_profiles[i] == profile) {
m_event.Signal();
break;
}
}
}
};
static_assert(sprofile::srv::IsIProfileUpdateObserver<ProfileUpdateObserverImpl>);
class ProfileUpdateObserverManager {
public:
static constexpr auto MaxObservers = 10;
private:
ProfileUpdateObserverImpl *m_observers[MaxObservers];
int m_observer_count;
os::SdkMutex m_mutex;
public:
ProfileUpdateObserverManager() : m_observer_count(0), m_mutex() { /* ... */ }
public:
Result OpenObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> &out, MemoryResource *memory_resource);
void CloseObserver(ProfileUpdateObserverImpl *observer);
void OnUpdate(Identifier profile) {
std::scoped_lock lk(m_mutex);
for (auto i = 0; i < m_observer_count; ++i) {
m_observers[i]->OnUpdate(profile);
}
}
};
}

View File

@@ -1,98 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_service_for_bg_agent.hpp"
#include "sprofile_srv_profile_importer_impl.hpp"
#include "sprofile_srv_fs_utils.hpp"
namespace ams::sprofile::srv {
Result ServiceForBgAgent::OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out) {
/* Allocate an object. */
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileImporter, ProfileImporterImpl>(m_memory_resource, m_profile_manager);
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
/* Confirm that we can begin an import. */
R_TRY(m_profile_manager->OpenProfileImporter());
/* Return the object. */
*out = std::move(obj);
R_SUCCEED();
}
Result ServiceForBgAgent::GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg) {
/* Check size. */
R_UNLESS(out.GetSize() >= arg.metadata.num_entries, sprofile::ResultInvalidArgument());
/* Load primary metadata. */
sprofile::srv::ProfileMetadata primary_metadata;
R_TRY_CATCH(m_profile_manager->LoadPrimaryMetadata(std::addressof(primary_metadata))) {
R_CATCH(fs::ResultPathNotFound) {
/* It's okay if we have no primary metadata -- this means that all profiles are importable. */
primary_metadata.num_entries = 0;
}
} R_END_TRY_CATCH;
/* We want to return the set of profiles that can be imported, which is just the profiles we don't already have. */
u32 count = 0;
for (u32 i = 0; i < arg.metadata.num_entries; ++i) {
const auto &arg_entry = arg.metadata.entries[i];
/* Check if we have the entry. */
bool have_entry = false;
for (u32 j = 0; j < primary_metadata.num_entries; ++j) {
const auto &pri_entry = primary_metadata.entries[j];
if (pri_entry.identifier_0 == arg_entry.identifier_0 && pri_entry.identifier_1 == arg_entry.identifier_1) {
have_entry = true;
break;
}
}
/* If we don't already have the entry, it's importable -- copy it out. */
if (!have_entry) {
out[count++] = arg.profile_urls[i];
}
}
/* Set output count. */
*out_count = count;
R_SUCCEED();
}
Result ServiceForBgAgent::IsUpdateNeeded(sf::Out<bool> out, Identifier revision_key) {
/* Load primary metadata. */
bool loaded_metadata = true;
sprofile::srv::ProfileMetadata primary_metadata;
R_TRY_CATCH(m_profile_manager->LoadPrimaryMetadata(std::addressof(primary_metadata))) {
R_CATCH(fs::ResultPathNotFound) {
/* If we have no metadata, we don't have a revision key. */
loaded_metadata = false;
}
} R_END_TRY_CATCH;
/* Determine if update is needed. */
*out = !(loaded_metadata && revision_key == primary_metadata.revision_key);
R_SUCCEED();
}
Result ServiceForBgAgent::Reset() {
R_RETURN(m_profile_manager->ResetSaveData());
}
}

View File

@@ -1,38 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_service_for_bg_agent.hpp"
namespace ams::sprofile::srv {
class ProfileManager;
class ServiceForBgAgent {
private:
MemoryResource *m_memory_resource;
ProfileManager *m_profile_manager;
public:
constexpr ServiceForBgAgent(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
public:
Result OpenProfileImporter(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileImporter>> out);
Result GetImportableProfileUrls(sf::Out<u32> out_count, const sf::OutArray<sprofile::srv::ProfileUrl> &out, const sprofile::srv::ProfileMetadataForImportMetadata &arg);
Result IsUpdateNeeded(sf::Out<bool> out, Identifier revision_key);
Result Reset();
};
static_assert(sprofile::srv::IsISprofileServiceForBgAgent<ServiceForBgAgent>);
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_profile_manager.hpp"
#include "sprofile_srv_service_for_system_process.hpp"
#include "sprofile_srv_profile_reader_impl.hpp"
#include "sprofile_srv_profile_controller_for_debug_impl.hpp"
namespace ams::sprofile::srv {
Result ServiceForSystemProcess::OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out) {
/* Allocate an object. */
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileReader, ProfileReaderImpl>(m_memory_resource, m_profile_manager);
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
/* Return the object. */
*out = std::move(obj);
R_SUCCEED();
}
Result ServiceForSystemProcess::OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out) {
R_RETURN(m_profile_manager->GetUpdateObserverManager().OpenObserver(out, m_memory_resource));
}
Result ServiceForSystemProcess::OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out) {
/* Require debug mode in order to open a debug controller. */
R_UNLESS(settings::fwdbg::IsDebugModeEnabled(), sprofile::ResultNotPermitted());
/* Allocate an object. */
auto obj = sf::ObjectFactory<sf::MemoryResourceAllocationPolicy>::CreateSharedEmplaced<IProfileControllerForDebug, ProfileControllerForDebugImpl>(m_memory_resource, m_profile_manager);
R_UNLESS(obj != nullptr, sprofile::ResultAllocationFailed());
/* Return the object. */
*out = std::move(obj);
R_SUCCEED();
}
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_service_for_system_process.hpp"
namespace ams::sprofile::srv {
class ProfileManager;
class ServiceForSystemProcess {
private:
MemoryResource *m_memory_resource;
ProfileManager *m_profile_manager;
public:
constexpr ServiceForSystemProcess(MemoryResource *mr, ProfileManager *pm) : m_memory_resource(mr), m_profile_manager(pm) { /* ... */ }
public:
Result OpenProfileReader(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileReader>> out);
Result OpenProfileUpdateObserver(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileUpdateObserver>> out);
Result OpenProfileControllerForDebug(sf::Out<sf::SharedPointer<::ams::sprofile::srv::IProfileControllerForDebug>> out);
};
static_assert(sprofile::srv::IsISprofileServiceForSystemProcess<ServiceForSystemProcess>);
}

View File

@@ -1,39 +0,0 @@
/*
* Copyright (c) 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 "sprofile_srv_service_getter.hpp"
namespace ams::sprofile::srv {
Result ServiceGetter::GetServiceForSystemProcess(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out) {
/* Check that we have a service-for-system-process. */
R_UNLESS(m_service_for_system_process != nullptr, sprofile::ResultNotPermitted());
/* Set the output. */
*out = m_service_for_system_process;
R_SUCCEED();
}
Result ServiceGetter::GetServiceForBgAgent(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out) {
/* Check that we have a service-for-bg-agent. */
R_UNLESS(m_service_for_bg_agent != nullptr, sprofile::ResultNotPermitted());
/* Set the output. */
*out = m_service_for_bg_agent;
R_SUCCEED();
}
}

View File

@@ -1,34 +0,0 @@
/*
* Copyright (c) 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>
#include "sprofile_srv_i_service_getter.hpp"
namespace ams::sprofile::srv {
class ServiceGetter {
private:
sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForBgAgent> m_service_for_bg_agent;
sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForSystemProcess> m_service_for_system_process;
public:
constexpr ServiceGetter(sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForBgAgent> bg, sf::SharedPointer<::ams::sprofile::srv::ISprofileServiceForSystemProcess> sp) : m_service_for_bg_agent(bg), m_service_for_system_process(sp) { /* ... */ }
public:
Result GetServiceForSystemProcess(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForSystemProcess>> out);
Result GetServiceForBgAgent(sf::Out<sf::SharedPointer<sprofile::srv::ISprofileServiceForBgAgent>> out);
};
static_assert(sprofile::srv::IsIServiceGetter<ServiceGetter>);
}

View File

@@ -1,152 +0,0 @@
/*
* Copyright (c) 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::sprofile::srv {
constexpr inline const u32 ProfileFormatVersion = 1;
constexpr inline bool IsValidProfileFormatVersion(u32 version) {
return version == ProfileFormatVersion;
}
enum ValueType : u8 {
ValueType_Byte = 0,
ValueType_U32 = 1,
ValueType_S32 = 2,
ValueType_U64 = 3,
ValueType_S64 = 4,
};
struct ProfileDataEntry {
Identifier key;
ValueType type;
union {
s64 value_s64;
u64 value_u64;
s32 value_s32;
u32 value_u32;
u8 value_u8;
};
};
static_assert(util::is_pod<ProfileDataEntry>::value);
static_assert(sizeof(ProfileDataEntry) == 0x10);
static_assert(AMS_OFFSETOF(ProfileDataEntry, key) == 0x00);
static_assert(AMS_OFFSETOF(ProfileDataEntry, type) == 0x07);
static_assert(AMS_OFFSETOF(ProfileDataEntry, value_s64) == 0x08);
struct ProfileData {
u32 num_entries;
u8 unk_04[0x0C];
u8 unk_10[0x20];
ProfileDataEntry entries[(0x4000 - 0x30) / sizeof(ProfileDataEntry)];
};
static_assert(util::is_pod<ProfileData>::value);
static_assert(sizeof(ProfileData) == 0x4000);
static_assert(AMS_OFFSETOF(ProfileData, num_entries) == 0x00);
static_assert(AMS_OFFSETOF(ProfileData, unk_04) == 0x04);
static_assert(AMS_OFFSETOF(ProfileData, unk_10) == 0x10);
static_assert(AMS_OFFSETOF(ProfileData, entries) == 0x30);
struct ServiceProfile {
Identifier name;
ProfileData data;
};
static_assert(util::is_pod<ServiceProfile>::value);
static_assert(sizeof(ServiceProfile) == 0x4008);
static_assert(AMS_OFFSETOF(ServiceProfile, name) == 0x00);
static_assert(AMS_OFFSETOF(ServiceProfile, data) == 0x08);
struct ProfileDataForImportData : public sf::LargeData, public sf::PrefersMapAliasTransferMode {
struct {
Identifier identifier_0;
Identifier identifier_1;
u8 unk_0E[2];
u32 version;
u8 unk_14[0x1C];
} header;
u8 hash[crypto::Md5Generator::HashSize];
ProfileData data;
u8 unk_4040[0x4400 - 0x4040];
};
static_assert(util::is_pod<ProfileDataForImportData>::value);
static_assert(sizeof(ProfileDataForImportData) == 0x4400);
static_assert(AMS_OFFSETOF(ProfileDataForImportData, header) == 0x00);
static_assert(AMS_OFFSETOF(ProfileDataForImportData, hash) == 0x30);
static_assert(AMS_OFFSETOF(ProfileDataForImportData, data) == 0x40);
static_assert(AMS_OFFSETOF(ProfileDataForImportData, unk_4040) == 0x4040);
struct ProfileMetadataEntry {
Identifier identifier_0;
Identifier identifier_1;
u8 unk_0E[0x32];
};
static_assert(util::is_pod<ProfileMetadataEntry>::value);
static_assert(sizeof(ProfileMetadataEntry) == 0x40);
static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_0) == 0x00);
static_assert(AMS_OFFSETOF(ProfileMetadataEntry, identifier_1) == 0x07);
static_assert(AMS_OFFSETOF(ProfileMetadataEntry, unk_0E) == 0x0E);
struct ProfileUrl : public sf::PrefersMapAliasTransferMode {
char url[0x100];
};
static_assert(util::is_pod<ProfileUrl>::value);
static_assert(sizeof(ProfileUrl) == 0x100);
struct ProfileMetadata {
u32 num_entries;
u32 unk_04;
Identifier revision_key;
u8 unk_0F[0x1];
u8 unk_10[0x30];
ProfileMetadataEntry entries[50];
};
static_assert(util::is_pod<ProfileMetadata>::value);
static_assert(sizeof(ProfileMetadata) == 0xCC0);
static_assert(AMS_OFFSETOF(ProfileMetadata, num_entries) == 0x00);
static_assert(AMS_OFFSETOF(ProfileMetadata, unk_04) == 0x04);
static_assert(AMS_OFFSETOF(ProfileMetadata, revision_key) == 0x08);
static_assert(AMS_OFFSETOF(ProfileMetadata, unk_0F) == 0x0F);
static_assert(AMS_OFFSETOF(ProfileMetadata, unk_10) == 0x10);
static_assert(AMS_OFFSETOF(ProfileMetadata, entries) == 0x40);
struct ProfileMetadataForImportMetadata : public sf::LargeData, public sf::PrefersMapAliasTransferMode {
struct {
u32 version;
u8 unk_04[0x1C];
} header;
u8 hash[crypto::Md5Generator::HashSize];
ProfileMetadata metadata;
ProfileUrl profile_urls[50];
u8 unk_3EF0[0x8000 - 0x3EF0];
};
static_assert(util::is_pod<ProfileMetadataForImportMetadata>::value);
static_assert(sizeof(ProfileMetadataForImportMetadata) == 0x8000);
static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, header) == 0x00);
static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, hash) == 0x20);
static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, metadata) == 0x30);
static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, profile_urls) == 0xCF0);
static_assert(AMS_OFFSETOF(ProfileMetadataForImportMetadata, unk_3EF0) == 0x3EF0);
}