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,56 +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/ncm/ncm_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_content_storage.hpp>
#include <stratosphere/ncm/ncm_i_content_manager.hpp>
#include <stratosphere/fs/fs_content_storage_id.hpp>
namespace ams::ncm {
/* Management. */
void Initialize();
void Finalize();
void InitializeWithObject(sf::SharedPointer<IContentManager> manager_object);
/* Service API. */
Result CreateContentStorage(StorageId storage_id);
Result CreateContentMetaDatabase(StorageId storage_id);
Result VerifyContentStorage(StorageId storage_id);
Result VerifyContentMetaDatabase(StorageId storage_id);
Result OpenContentStorage(ContentStorage *out, StorageId storage_id);
Result OpenContentMetaDatabase(ContentMetaDatabase *out, StorageId storage_id);
Result CleanupContentMetaDatabase(StorageId storage_id);
Result ActivateContentStorage(StorageId storage_id);
Result InactivateContentStorage(StorageId storage_id);
Result ActivateContentMetaDatabase(StorageId storage_id);
Result InactivateContentMetaDatabase(StorageId storage_id);
Result InvalidateRightsIdCache();
Result ActivateFsContentStorage(fs::ContentStorageId fs_content_storage_id);
/* Deprecated API. */
Result CloseContentStorageForcibly(StorageId storage_id);
Result CloseContentMetaDatabaseForcibly(StorageId storage_id);
}

View File

@@ -1,89 +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 <vapours.hpp>
namespace ams::ncm {
class AutoBuffer {
NON_COPYABLE(AutoBuffer);
private:
u8 *m_buffer;
size_t m_size;
public:
AutoBuffer() : m_buffer(nullptr), m_size(0) { /* ... */ }
~AutoBuffer() {
this->Reset();
}
AutoBuffer(AutoBuffer &&rhs) {
m_buffer = rhs.m_buffer;
m_size = rhs.m_size;
rhs.m_buffer = nullptr;
rhs.m_size = 0;
}
AutoBuffer &operator=(AutoBuffer &&rhs) {
AutoBuffer(std::move(rhs)).Swap(*this);
return *this;
}
void Swap(AutoBuffer &rhs) {
std::swap(m_buffer, rhs.m_buffer);
std::swap(m_size, rhs.m_size);
}
void Reset() {
if (m_buffer != nullptr) {
delete[] m_buffer;
m_buffer = nullptr;
m_size = 0;
}
}
u8 *Get() const {
return m_buffer;
}
size_t GetSize() const {
return m_size;
}
Result Initialize(size_t size) {
/* Check that we're not already initialized. */
AMS_ABORT_UNLESS(m_buffer == nullptr);
/* Allocate a buffer. */
m_buffer = new (std::nothrow) u8[size];
R_UNLESS(m_buffer != nullptr, ncm::ResultAllocationFailed());
m_size = size;
R_SUCCEED();
}
Result Initialize(const void *buf, size_t size) {
/* Create a new buffer of the right size. */
R_TRY(this->Initialize(size));
/* Copy the input data in. */
std::memcpy(m_buffer, buf, size);
R_SUCCEED();
}
};
}

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 <vapours.hpp>
namespace ams::ncm {
template<class Key, class Value, size_t N>
using BoundedMap = util::BoundedMap<Key, Value, N>;
}

View File

@@ -1,45 +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 <vapours.hpp>
namespace ams::ncm {
struct ContentId {
util::Uuid uuid;
bool operator==(const ContentId &other) const {
return this->uuid == other.uuid;
}
bool operator!=(const ContentId &other) const {
return this->uuid != other.uuid;
}
bool operator==(const util::Uuid &other) const {
return this->uuid == other;
}
bool operator!=(const util::Uuid &other) const {
return this->uuid != other;
}
};
static_assert(alignof(ContentId) == 1);
constexpr inline ContentId InvalidContentId = { util::InvalidUuid };
}

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/>.
*/
#pragma once
#include <stratosphere/fs/fs_rights_id.hpp>
#include <stratosphere/ncm/ncm_content_id.hpp>
#include <stratosphere/ncm/ncm_content_info_data.hpp>
namespace ams::ncm {
constexpr inline size_t ContentIdStringLength = 2 * sizeof(ContentId);
constexpr inline size_t RightsIdStringLength = 2 * sizeof(fs::RightsId);
constexpr inline size_t TicketFileStringLength = RightsIdStringLength + 4;
constexpr inline size_t CertFileStringLength = RightsIdStringLength + 5;
struct ContentIdString {
char data[ContentIdStringLength + 1];
};
ContentIdString GetContentIdString(ContentId id);
void GetStringFromContentId(char *dst, size_t dst_size, ContentId id);
void GetStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
void GetTicketFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
void GetCertificateFileStringFromRightsId(char *dst, size_t dst_size, fs::RightsId id);
util::optional<ContentId> GetContentIdFromString(const char *str, size_t len);
}

View File

@@ -1,70 +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/fs/fs_content_attributes.hpp>
#include <stratosphere/ncm/ncm_content_id.hpp>
#include <stratosphere/ncm/ncm_content_type.hpp>
namespace ams::ncm {
struct ContentInfo {
static constexpr fs::ContentAttributes DefaultContentAttributes = fs::ContentAttributes_None;
ContentId content_id;
u32 size_low;
u8 size_high;
u8 content_attributes;
ContentType content_type;
u8 id_offset;
constexpr const ContentId &GetId() const {
return this->content_id;
}
constexpr u64 GetSize() const {
return (static_cast<u64>(this->size_high) << 32) | static_cast<u64>(this->size_low);
}
constexpr fs::ContentAttributes GetContentAttributes() const {
return static_cast<fs::ContentAttributes>(this->content_attributes & 0xF);
}
constexpr ContentType GetType() const {
return this->content_type;
}
constexpr u8 GetIdOffset() const {
return this->id_offset;
}
static constexpr ContentInfo Make(ContentId id, u64 size, fs::ContentAttributes attr, ContentType type, u8 id_ofs = 0) {
const u32 size_low = size & 0xFFFFFFFFu;
const u8 size_high = static_cast<u8>(size >> 32);
return {
.content_id = id,
.size_low = size_low,
.size_high = size_high,
.content_attributes = attr,
.content_type = type,
.id_offset = id_ofs,
};
}
};
static_assert(sizeof(util::is_pod<ContentInfo>::value));
static_assert(sizeof(ContentInfo) == 0x18);
}

View File

@@ -1,130 +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/ncm/ncm_content_info.hpp>
#include <stratosphere/ncm/ncm_content_storage.hpp>
#include <stratosphere/ncm/ncm_storage_id.hpp>
#include <stratosphere/ncm/ncm_content_meta_key.hpp>
namespace ams::ncm {
struct Digest {
u8 data[crypto::Sha256Generator::HashSize];
};
enum class InstallState : u8 {
NotPrepared,
Prepared,
Installed,
AlreadyExists,
};
struct PackagedContentInfo {
Digest digest;
ContentInfo info;
constexpr const ContentId &GetId() const {
return this->info.GetId();
}
constexpr fs::ContentAttributes GetContentAttributes() const {
return this->info.GetContentAttributes();
}
constexpr ContentType GetType() const {
return this->info.GetType();
}
constexpr u8 GetIdOffset() const {
return this->info.GetIdOffset();
}
};
struct InstallContentInfo {
Digest digest;
crypto::Sha256Context context;
u8 buffered_data[crypto::Sha256Generator::BlockSize];
u64 buffered_data_size;
ContentInfo info;
PlaceHolderId placeholder_id;
ContentMetaType meta_type;
InstallState install_state;
bool verify_digest;
StorageId storage_id;
bool is_temporary;
bool is_sha256_calculated;
s64 written;
constexpr const ContentId &GetId() const {
return this->info.GetId();
}
constexpr u64 GetSize() const {
return this->info.GetSize();
}
constexpr fs::ContentAttributes GetContentAttributes() const {
return this->info.GetContentAttributes();
}
constexpr ContentType GetType() const {
return this->info.GetType();
}
constexpr u8 GetIdOffset() const {
return this->info.GetIdOffset();
}
constexpr const PlaceHolderId &GetPlaceHolderId() const {
return this->placeholder_id;
}
constexpr ContentMetaType GetContentMetaType() const {
return this->meta_type;
}
constexpr InstallState GetInstallState() const {
return this->install_state;
}
constexpr StorageId GetStorageId() const {
return this->storage_id;
}
constexpr s64 GetSizeWritten() const {
return this->written;
}
static constexpr InstallContentInfo Make(const ContentInfo &info, ContentMetaType meta_type) {
return {
.info = info,
.meta_type = meta_type,
};
}
static constexpr InstallContentInfo Make(const PackagedContentInfo &info, ContentMetaType meta_type) {
return {
.digest = info.digest,
.info = info.info,
.meta_type = meta_type,
.verify_digest = true,
};
}
};
static_assert(sizeof(InstallContentInfo) == 0xC8);
}

View File

@@ -1,31 +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 <vapours.hpp>
#include <stratosphere/ncm/ncm_content_meta_key.hpp>
namespace ams::ncm {
constexpr inline s64 MaxClusterSize = 256_KB;
s64 CalculateRequiredSize(s64 file_size, s64 cluster_size = MaxClusterSize);
s64 CalculateRequiredSizeForExtension(s64 file_size, s64 cluster_size = MaxClusterSize);
class ContentMetaDatabase;
Result EstimateRequiredSize(s64 *out_size, const ContentMetaKey &key, ContentMetaDatabase *db);
}

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/>.
*/
#pragma once
#include <stratosphere/ncm/ncm_content_meta.hpp>
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_content_storage.hpp>
namespace ams::ncm {
class ContentMetaDatabaseBuilder {
private:
ContentMetaDatabase *m_db;
private:
Result BuildFromPackageContentMeta(void *buf, size_t size, const ContentInfo &meta_info);
public:
explicit ContentMetaDatabaseBuilder(ContentMetaDatabase *d) : m_db(d) { /* ... */ }
Result BuildFromStorage(ContentStorage *storage);
Result BuildFromPackage(const char *package_root_path);
Result Cleanup();
};
Result ListApplicationPackage(s32 *out_count, ApplicationId *out_ids, s32 max_out_ids, const char *package_root_path);
}

View File

@@ -1,43 +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 <vapours.hpp>
namespace ams::ncm {
struct ContentManagerConfig {
bool build_system_database;
bool import_database_from_system_on_sd;
bool enable_integrated_system_content;
bool HasAnyConfig() const {
return this->ShouldBuildDatabase() || this->import_database_from_system_on_sd || this->enable_integrated_system_content;
}
bool ShouldBuildDatabase() const {
return hos::GetVersion() < hos::Version_4_0_0 || this->build_system_database;
}
bool ShouldImportDatabaseFromSignedSystemPartitionOnSd() const {
return this->import_database_from_system_on_sd;
}
bool IsIntegratedSystemContentEnabled() const {
return this->enable_integrated_system_content;
}
};
}

View File

@@ -1,269 +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/os.hpp>
#include <stratosphere/fs/fs_mount.hpp>
#include <stratosphere/fs/fs_bis.hpp>
#include <stratosphere/fs/fs_content_storage.hpp>
#include <stratosphere/fs/fs_system_save_data.hpp>
#include <stratosphere/ncm/ncm_i_content_manager.hpp>
#include <stratosphere/ncm/ncm_content_manager_config.hpp>
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_bounded_map.hpp>
#include <stratosphere/ncm/ncm_rights_id_cache.hpp>
#include <stratosphere/ncm/ncm_content_management_utils.hpp>
#include <stratosphere/ncm/ncm_content_meta_utils.hpp>
#include <stratosphere/ncm/ncm_registered_host_content.hpp>
#include <stratosphere/ncm/ncm_integrated_content_meta_database_impl.hpp>
#include <stratosphere/ncm/ncm_integrated_content_storage_impl.hpp>
#include <stratosphere/kvdb/kvdb_memory_key_value_store.hpp>
namespace ams::ncm {
class ContentMetaMemoryResource : public MemoryResource {
private:
mem::StandardAllocator m_allocator;
size_t m_peak_total_alloc_size;
size_t m_peak_alloc_size;
public:
explicit ContentMetaMemoryResource(void *heap, size_t heap_size) : m_allocator(heap, heap_size), m_peak_total_alloc_size(0), m_peak_alloc_size(0) { /* ... */ }
mem::StandardAllocator *GetAllocator() { return std::addressof(m_allocator); }
size_t GetPeakTotalAllocationSize() const { return m_peak_total_alloc_size; }
size_t GetPeakAllocationSize() const { return m_peak_alloc_size; }
private:
virtual void *AllocateImpl(size_t size, size_t alignment) override {
void *mem = m_allocator.Allocate(size, alignment);
m_peak_total_alloc_size = std::max(m_allocator.Hash().allocated_size, m_peak_total_alloc_size);
m_peak_alloc_size = std::max(size, m_peak_alloc_size);
return mem;
}
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
AMS_UNUSED(size, alignment);
return m_allocator.Free(buffer);
}
virtual bool IsEqualImpl(const MemoryResource &resource) const override {
return this == std::addressof(resource);
}
};
struct SystemSaveDataInfo {
u64 id;
u64 size;
u64 journal_size;
u32 flags;
fs::SaveDataSpaceId space_id;
};
static_assert(util::is_pod<SystemSaveDataInfo>::value);
struct IntegratedContentStorageImpl;
class ContentManagerImpl {
private:
constexpr static size_t MaxContentStorageRoots = 8;
constexpr static size_t MaxIntegratedContentStorageRoots = 8;
constexpr static size_t MaxContentMetaDatabaseRoots = 8;
constexpr static size_t MaxIntegratedContentMetaDatabaseRoots = 8;
constexpr static size_t MaxConfigs = 8;
constexpr static size_t MaxIntegratedConfigs = 8;
private:
struct ContentStorageConfig {
fs::ContentStorageId content_storage_id;
bool skip_verify_and_create;
bool skip_activate;
};
struct IntegratedContentStorageConfig {
ncm::StorageId storage_id;
fs::ContentStorageId content_storage_ids[MaxContentStorageRoots];
int num_content_storage_ids;
bool is_integrated;
};
private:
struct ContentStorageRoot {
NON_COPYABLE(ContentStorageRoot);
NON_MOVEABLE(ContentStorageRoot);
char mount_name[fs::MountNameLengthMax + 1];
char path[128];
StorageId storage_id;
util::optional<ContentStorageConfig> config;
sf::SharedPointer<IContentStorage> content_storage;
ContentStorageRoot() : mount_name(), path(), storage_id(), config(util::nullopt), content_storage() { /* ... */ }
};
struct IntegratedContentStorageRoot {
NON_COPYABLE(IntegratedContentStorageRoot);
NON_MOVEABLE(IntegratedContentStorageRoot);
const IntegratedContentStorageConfig *m_config;
ContentStorageRoot *m_roots;
int m_num_roots;
sf::EmplacedRef<IContentStorage, IntegratedContentStorageImpl> m_integrated_content_storage;
IntegratedContentStorageRoot() : m_config(), m_roots(), m_num_roots(), m_integrated_content_storage() { /* ... */ }
Result Create();
Result Verify();
Result Open(sf::Out<sf::SharedPointer<IContentStorage>> out, RightsIdCache &rights_id_cache, RegisteredHostContent &registered_host_content);
Result Activate(RightsIdCache &rights_id_cache, RegisteredHostContent &registered_host_content);
Result Inactivate(RegisteredHostContent &registered_host_content);
Result Activate(ContentStorageRoot &root, RightsIdCache &rights_id_cache, RegisteredHostContent &registered_host_content);
Result Activate(RightsIdCache &rights_id_cache, RegisteredHostContent &registered_host_content, fs::ContentStorageId content_storage_id);
ContentStorageRoot *GetRoot(fs::ContentStorageId storage_id) {
for (auto i = 0; i < m_num_roots; ++i) {
if (auto &root = m_roots[i]; root.config.has_value() && root.config->content_storage_id == storage_id) {
return std::addressof(root);
}
}
return nullptr;
}
};
struct ContentMetaDatabaseRoot {
NON_COPYABLE(ContentMetaDatabaseRoot);
NON_MOVEABLE(ContentMetaDatabaseRoot);
char mount_name[fs::MountNameLengthMax + 1];
char path[128];
StorageId storage_id;
util::optional<ContentStorageConfig> storage_config;
util::optional<SystemSaveDataInfo> save_data_info;
util::optional<kvdb::MemoryKeyValueStore<ContentMetaKey>> kvs;
sf::SharedPointer<IContentMetaDatabase> content_meta_database;
ContentMetaMemoryResource *memory_resource;
u32 max_content_metas;
ContentMetaDatabaseRoot() : mount_name(), path(), storage_id(), storage_config(util::nullopt), save_data_info(util::nullopt), kvs(util::nullopt), content_meta_database(), memory_resource(), max_content_metas() { /* ... */ }
};
struct IntegratedContentMetaDatabaseRoot {
NON_COPYABLE(IntegratedContentMetaDatabaseRoot);
NON_MOVEABLE(IntegratedContentMetaDatabaseRoot);
const IntegratedContentStorageConfig *m_config;
ContentMetaDatabaseRoot *m_roots;
int m_num_roots;
sf::EmplacedRef<IContentMetaDatabase, IntegratedContentMetaDatabaseImpl> m_integrated_content_meta_database;
IntegratedContentMetaDatabaseRoot() : m_config(), m_roots(), m_num_roots(), m_integrated_content_meta_database() { /* ... */ }
Result Create();
Result Verify();
Result Open(sf::Out<sf::SharedPointer<IContentMetaDatabase>> out);
Result Cleanup();
Result Activate();
Result Inactivate();
Result Activate(ContentMetaDatabaseRoot &root);
Result Activate(fs::ContentStorageId content_storage_id);
ContentMetaDatabaseRoot *GetRoot(fs::ContentStorageId storage_id) {
for (auto i = 0; i < m_num_roots; ++i) {
if (auto &root = m_roots[i]; root.storage_config.has_value() && root.storage_config->content_storage_id == storage_id) {
return std::addressof(root);
}
}
return nullptr;
}
};
private:
os::SdkRecursiveMutex m_mutex{};
bool m_initialized{false};
IntegratedContentStorageRoot m_integrated_content_storage_roots[MaxIntegratedContentStorageRoots]{};
ContentStorageRoot m_content_storage_roots[MaxContentStorageRoots]{};
IntegratedContentMetaDatabaseRoot m_integrated_content_meta_database_roots[MaxIntegratedContentMetaDatabaseRoots]{};
ContentMetaDatabaseRoot m_content_meta_database_roots[MaxContentMetaDatabaseRoots]{};
IntegratedContentStorageConfig m_integrated_configs[MaxIntegratedConfigs]{};
ContentStorageConfig m_configs[MaxConfigs]{};
u32 m_num_integrated_content_storage_entries{0};
u32 m_num_content_storage_entries{0};
u32 m_num_integrated_content_meta_entries{0};
u32 m_num_content_meta_entries{0};
u32 m_num_integrated_configs{0};
u32 m_num_configs{0};
RightsIdCache m_rights_id_cache{};
RegisteredHostContent m_registered_host_content{};
public:
ContentManagerImpl() = default;
~ContentManagerImpl();
public:
Result Initialize(const ContentManagerConfig &config);
private:
Result Initialize(const ContentManagerConfig &manager_config, const IntegratedContentStorageConfig *integrated_configs, size_t num_integrated_configs, const ContentStorageConfig *configs, size_t num_configs, const ncm::StorageId *activated_storages, size_t num_activated_storages);
Result InitializeStorageBuiltInSystem(const ContentManagerConfig &manager_config);
Result InitializeStorage(ncm::StorageId storage_id);
const ContentStorageConfig &GetContentStorageConfig(fs::ContentStorageId content_storage_id) {
for (size_t i = 0; i < m_num_configs; ++i) {
if (m_configs[i].content_storage_id == content_storage_id) {
return m_configs[i];
}
}
/* NOTE: Nintendo accesses out of bounds memory here. Should we explicitly abort? This is guaranteed by data to never happen. */
AMS_ASSUME(false);
}
private:
/* Helpers. */
Result GetIntegratedContentStorageConfig(IntegratedContentStorageConfig **out, fs::ContentStorageId content_storage_id);
Result GetIntegratedContentStorageRoot(IntegratedContentStorageRoot **out, StorageId id);
Result GetIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot **out, StorageId id);
Result InitializeContentStorageRoot(ContentStorageRoot *out, StorageId storage_id, util::optional<ContentStorageConfig> config);
Result InitializeContentMetaDatabaseRoot(ContentMetaDatabaseRoot *out, StorageId storage_id, util::optional<ContentStorageConfig> storage_config);
Result InitializeIntegratedContentStorageRoot(IntegratedContentStorageRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
Result InitializeIntegratedContentMetaDatabaseRoot(IntegratedContentMetaDatabaseRoot *out, const IntegratedContentStorageConfig *config, size_t root_idx, size_t root_count);
Result BuildContentMetaDatabase(StorageId storage_id);
Result BuildContentMetaDatabaseImpl(StorageId storage_id);
Result ImportContentMetaDatabase(StorageId storage_id, bool from_signed_partition);
Result ImportContentMetaDatabaseImpl(ContentMetaDatabaseRoot *root, const char *import_mount_name);
private:
/* Helpers for unofficial functionality. */
bool IsNeedRebuildSystemContentMetaDatabase();
public:
/* Actual commands. */
Result CreateContentStorage(StorageId storage_id);
Result CreateContentMetaDatabase(StorageId storage_id);
Result VerifyContentStorage(StorageId storage_id);
Result VerifyContentMetaDatabase(StorageId storage_id);
Result OpenContentStorage(sf::Out<sf::SharedPointer<IContentStorage>> out, StorageId storage_id);
Result OpenContentMetaDatabase(sf::Out<sf::SharedPointer<IContentMetaDatabase>> out, StorageId storage_id);
Result CloseContentStorageForcibly(StorageId storage_id);
Result CloseContentMetaDatabaseForcibly(StorageId storage_id);
Result CleanupContentMetaDatabase(StorageId storage_id);
Result ActivateContentStorage(StorageId storage_id);
Result InactivateContentStorage(StorageId storage_id);
Result ActivateContentMetaDatabase(StorageId storage_id);
Result InactivateContentMetaDatabase(StorageId storage_id);
Result InvalidateRightsIdCache();
Result GetMemoryReport(sf::Out<MemoryReport> out);
Result ActivateFsContentStorage(fs::ContentStorageId fs_content_storage_id);
};
static_assert(IsIContentManager<ContentManagerImpl>);
}

View File

@@ -1,399 +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/ncm/ncm_content_meta_id.hpp>
#include <stratosphere/ncm/ncm_content_meta_key.hpp>
#include <stratosphere/ncm/ncm_content_meta_platform.hpp>
#include <stratosphere/ncm/ncm_content_info.hpp>
#include <stratosphere/ncm/ncm_content_info_data.hpp>
#include <stratosphere/ncm/ncm_firmware_variation.hpp>
#include <stratosphere/ncm/ncm_storage_id.hpp>
namespace ams::ncm {
enum ContentMetaAttribute : u8 {
ContentMetaAttribute_None = (0 << 0),
ContentMetaAttribute_IncludesExFatDriver = (1 << 0),
ContentMetaAttribute_Rebootless = (1 << 1),
ContentMetaAttribute_Compacted = (1 << 2),
};
struct ContentMetaInfo {
u64 id;
u32 version;
ContentMetaType type;
u8 attributes;
u8 padding[2];
static constexpr ContentMetaInfo Make(u64 id, u32 version, ContentMetaType type, u8 attributes) {
return {
.id = id,
.version = version,
.type = type,
.attributes = attributes,
};
}
constexpr ContentMetaKey ToKey() const {
return ContentMetaKey::Make(this->id, this->version, this->type);
}
};
static_assert(sizeof(ContentMetaInfo) == 0x10);
struct ContentMetaHeader {
u16 extended_header_size;
u16 content_count;
u16 content_meta_count;
u8 attributes;
ContentMetaPlatform platform;
};
static_assert(sizeof(ContentMetaHeader) == 0x8);
struct PackagedContentMetaHeader {
u64 id;
u32 version;
ContentMetaType type;
ContentMetaPlatform platform;
u16 extended_header_size;
u16 content_count;
u16 content_meta_count;
u8 attributes;
u8 storage_id;
ContentInstallType install_type;
bool committed;
u32 required_download_system_version;
u8 reserved_1C[4];
};
static_assert(sizeof(PackagedContentMetaHeader) == 0x20);
static_assert(AMS_OFFSETOF(PackagedContentMetaHeader, reserved_1C) == 0x1C);
using InstallContentMetaHeader = PackagedContentMetaHeader;
struct ApplicationMetaExtendedHeader {
PatchId patch_id;
u32 required_system_version;
u32 required_application_version;
};
struct PatchMetaExtendedHeader {
ApplicationId application_id;
u32 required_system_version;
u32 extended_data_size;
u8 reserved[0x8];
};
struct AddOnContentMetaExtendedHeader {
ApplicationId application_id;
u32 required_application_version;
u8 content_accessibilities;
u8 padding[3];
DataPatchId data_patch_id;
};
struct LegacyAddOnContentMetaExtendedHeader {
ApplicationId application_id;
u32 required_application_version;
u32 padding;
};
struct DeltaMetaExtendedHeader {
ApplicationId application_id;
u32 extended_data_size;
u32 padding;
};
struct SystemUpdateMetaExtendedHeader {
u32 extended_data_size;
};
template<typename ContentMetaHeaderType, typename ContentInfoType>
class ContentMetaAccessor {
public:
using HeaderType = ContentMetaHeaderType;
using InfoType = ContentInfoType;
private:
void *m_data;
const size_t m_size;
bool m_is_header_valid;
private:
static size_t GetExtendedHeaderSize(ContentMetaType type) {
switch (type) {
case ContentMetaType::Application: return sizeof(ApplicationMetaExtendedHeader);
case ContentMetaType::Patch: return sizeof(PatchMetaExtendedHeader);
case ContentMetaType::AddOnContent: return sizeof(AddOnContentMetaExtendedHeader);
case ContentMetaType::Delta: return sizeof(DeltaMetaExtendedHeader);
default: return 0;
}
}
protected:
constexpr ContentMetaAccessor(const void *d, size_t sz) : m_data(const_cast<void *>(d)), m_size(sz), m_is_header_valid(true) { /* ... */ }
constexpr ContentMetaAccessor(void *d, size_t sz) : m_data(d), m_size(sz), m_is_header_valid(false) { /* ... */ }
template<class NewHeaderType, class NewInfoType>
static constexpr size_t CalculateSizeImpl(size_t ext_header_size, size_t content_count, size_t content_meta_count, size_t extended_data_size, bool has_digest) {
return sizeof(NewHeaderType) + ext_header_size + content_count * sizeof(NewInfoType) + content_meta_count * sizeof(ContentMetaInfo) + extended_data_size + (has_digest ? sizeof(Digest) : 0);
}
static constexpr size_t CalculateSize(ContentMetaType type, size_t content_count, size_t content_meta_count, size_t extended_data_size, bool has_digest = false) {
return CalculateSizeImpl<ContentMetaHeaderType, ContentInfoType>(GetExtendedHeaderSize(type), content_count, content_meta_count, extended_data_size, has_digest);
}
uintptr_t GetExtendedHeaderAddress() const {
return reinterpret_cast<uintptr_t>(m_data) + sizeof(HeaderType);
}
uintptr_t GetContentInfoStartAddress() const {
return this->GetExtendedHeaderAddress() + this->GetExtendedHeaderSize();
}
uintptr_t GetContentInfoAddress(size_t i) const {
return this->GetContentInfoStartAddress() + i * sizeof(InfoType);
}
uintptr_t GetContentMetaInfoStartAddress() const {
return this->GetContentInfoAddress(this->GetContentCount());
}
uintptr_t GetContentMetaInfoAddress(size_t i) const {
return this->GetContentMetaInfoStartAddress() + i * sizeof(ContentMetaInfo);
}
uintptr_t GetExtendedDataAddress() const {
return this->GetContentMetaInfoAddress(this->GetContentMetaCount());
}
uintptr_t GetDigestAddress() const {
return this->GetExtendedDataAddress() + this->GetExtendedDataSize();
}
InfoType *GetWritableContentInfo(size_t i) const {
AMS_ABORT_UNLESS(i < this->GetContentCount());
return reinterpret_cast<InfoType *>(this->GetContentInfoAddress(i));
}
InfoType *GetWritableContentInfo(ContentType type) const {
InfoType *found = nullptr;
for (size_t i = 0; i < this->GetContentCount(); i++) {
/* We want to find the info with the lowest id offset and the correct type. */
InfoType *info = this->GetWritableContentInfo(i);
if (info->GetType() == type && (found == nullptr || info->GetIdOffset() < found->GetIdOffset())) {
found = info;
}
}
return found;
}
InfoType *GetWritableContentInfo(ContentType type, u8 id_ofs) const {
for (size_t i = 0; i < this->GetContentCount(); i++) {
/* We want to find the info with the correct id offset and the correct type. */
if (InfoType *info = this->GetWritableContentInfo(i); info->GetType() == type && info->GetIdOffset() == id_ofs) {
return info;
}
}
return nullptr;
}
s64 CalculateContentRequiredSize() const {
s64 required_size = 0;
for (size_t i = 0; i < this->GetContentCount(); i++) {
required_size += CalculateRequiredSize(this->GetContentInfo(i)->info.GetSize());
}
return required_size;
}
void SetStorageId(StorageId storage_id) {
this->GetWritableHeader()->storage_id = static_cast<u8>(storage_id);
}
public:
const void *GetData() const {
return m_data;
}
size_t GetSize() const {
return m_size;
}
HeaderType *GetWritableHeader() const {
AMS_ABORT_UNLESS(m_is_header_valid);
return reinterpret_cast<HeaderType *>(m_data);
}
const HeaderType *GetHeader() const {
AMS_ABORT_UNLESS(m_is_header_valid);
return static_cast<const HeaderType *>(m_data);
}
ContentMetaKey GetKey() const {
auto header = this->GetHeader();
return ContentMetaKey::Make(header->id, header->version, header->type, header->install_type);
}
size_t GetExtendedHeaderSize() const {
return this->GetHeader()->extended_header_size;
}
template<typename ExtendedHeaderType>
const ExtendedHeaderType *GetExtendedHeader() const {
return reinterpret_cast<const ExtendedHeaderType *>(this->GetExtendedHeaderAddress());
}
size_t GetContentCount() const {
return this->GetHeader()->content_count;
}
const InfoType *GetContentInfo(size_t i) const {
AMS_ABORT_UNLESS(i < this->GetContentCount());
return this->GetWritableContentInfo(i);
}
const InfoType *GetContentInfo(ContentType type) const {
return this->GetWritableContentInfo(type);
}
const InfoType *GetContentInfo(ContentType type, u8 id_ofs) const {
return this->GetWritableContentInfo(type, id_ofs);
}
size_t GetContentMetaCount() const {
return this->GetHeader()->content_meta_count;
}
const ContentMetaInfo *GetContentMetaInfo(size_t i) const {
AMS_ABORT_UNLESS(i < this->GetContentMetaCount());
return reinterpret_cast<const ContentMetaInfo *>(this->GetContentMetaInfoAddress(i));
}
size_t GetExtendedDataSize() const {
switch (this->GetHeader()->type) {
case ContentMetaType::Patch: return this->GetExtendedHeader<PatchMetaExtendedHeader>()->extended_data_size;
case ContentMetaType::Delta: return this->GetExtendedHeader<DeltaMetaExtendedHeader>()->extended_data_size;
case ContentMetaType::SystemUpdate: return this->GetExtendedHeaderSize() == 0 ? 0 : this->GetExtendedHeader<SystemUpdateMetaExtendedHeader>()->extended_data_size;
default: return 0;
}
}
const void *GetExtendedData() const {
return reinterpret_cast<const void *>(this->GetExtendedDataAddress());
}
const Digest *GetDigest() const {
return reinterpret_cast<Digest *>(this->GetDigestAddress());
}
bool HasContent(const ContentId &id) const {
for (size_t i = 0; i < this->GetContentCount(); i++) {
if (id == this->GetContentInfo(i)->GetId()) {
return true;
}
}
return false;
}
StorageId GetStorageId() const {
return static_cast<StorageId>(this->GetHeader()->storage_id);
}
util::optional<ApplicationId> GetApplicationId(const ContentMetaKey &key) const {
switch (key.type) {
case ContentMetaType::Application: return ApplicationId{ key.id };
case ContentMetaType::Patch: return this->GetExtendedHeader<PatchMetaExtendedHeader>()->application_id;
case ContentMetaType::AddOnContent: return this->GetExtendedHeader<AddOnContentMetaExtendedHeader>()->application_id;
case ContentMetaType::Delta: return this->GetExtendedHeader<DeltaMetaExtendedHeader>()->application_id;
default: return util::nullopt;
}
}
util::optional<ApplicationId> GetApplicationId() const {
return this->GetApplicationId(this->GetKey());
}
};
class ContentMetaReader : public ContentMetaAccessor<ContentMetaHeader, ContentInfo> {
public:
constexpr ContentMetaReader(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
using ContentMetaAccessor::CalculateSize;
};
class PackagedContentMetaReader : public ContentMetaAccessor<PackagedContentMetaHeader, PackagedContentInfo> {
public:
constexpr PackagedContentMetaReader(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
size_t CalculateConvertInstallContentMetaSize() const;
void ConvertToInstallContentMeta(void *dst, size_t size, const InstallContentInfo &meta);
size_t CalculateConvertContentMetaSize() const;
void ConvertToContentMeta(void *dst, size_t size, const ContentInfo &meta);
size_t CalculateConvertFragmentOnlyInstallContentMetaSize(s32 fragment_count) const {
return CalculateSizeImpl<InstallContentMetaHeader, InstallContentInfo>(this->GetExtendedHeaderSize(), fragment_count + 1, 0, 0, false);
}
Result CalculateConvertFragmentOnlyInstallContentMetaSize(size_t *out_size, u32 source_version) const;
Result ConvertToFragmentOnlyInstallContentMeta(void *dst, size_t size, const InstallContentInfo &content_info, u32 source_version);
size_t CountDeltaFragments() const;
static constexpr size_t CalculateSize(ContentMetaType type, size_t content_count, size_t content_meta_count, size_t extended_data_size) {
return ContentMetaAccessor::CalculateSize(type, content_count, content_meta_count, extended_data_size, true);
}
size_t GetExtendedDataOffset() const {
return this->GetExtendedDataAddress() - reinterpret_cast<uintptr_t>(this->GetData());
}
};
class InstallContentMetaReader : public ContentMetaAccessor<InstallContentMetaHeader, InstallContentInfo> {
public:
constexpr InstallContentMetaReader(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
using ContentMetaAccessor::CalculateSize;
using ContentMetaAccessor::CalculateContentRequiredSize;
using ContentMetaAccessor::GetStorageId;
size_t CalculateConvertSize() const;
void ConvertToContentMeta(void *dst, size_t size) const;
};
class InstallContentMetaWriter : public ContentMetaAccessor<InstallContentMetaHeader, InstallContentInfo> {
public:
InstallContentMetaWriter(const void *data, size_t size) : ContentMetaAccessor(data, size) { /* ... */ }
using ContentMetaAccessor::CalculateSize;
using ContentMetaAccessor::CalculateContentRequiredSize;
using ContentMetaAccessor::GetWritableContentInfo;
using ContentMetaAccessor::SetStorageId;
};
class PatchMetaExtendedDataAccessor;
struct PatchDeltaHeader;
class AutoBuffer;
class MetaConverter {
public:
static Result CountContentExceptForMeta(s32 *out, PatchMetaExtendedDataAccessor *accessor, const PatchDeltaHeader &header, s32 delta_index);
static Result FindDeltaIndex(s32 *out, PatchMetaExtendedDataAccessor *accessor, u32 source_version, u32 destination_version);
static Result GetFragmentOnlyInstallContentMeta(AutoBuffer *out, const InstallContentInfo &content_info, const PackagedContentMetaReader &reader, PatchMetaExtendedDataAccessor *accessor, u32 source_version);
};
}

View File

@@ -1,236 +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/ncm/ncm_i_content_meta_database.hpp>
namespace ams::ncm {
class ContentMetaDatabase {
NON_COPYABLE(ContentMetaDatabase);
public:
struct ListCount {
s32 written;
s32 total;
};
private:
sf::SharedPointer<IContentMetaDatabase> m_interface;
public:
ContentMetaDatabase() : m_interface(nullptr) { /* ... */ }
explicit ContentMetaDatabase(sf::SharedPointer<IContentMetaDatabase> intf) : m_interface(intf) { /* ... */ }
ContentMetaDatabase(ContentMetaDatabase &&rhs) {
m_interface = std::move(rhs.m_interface);
}
ContentMetaDatabase &operator=(ContentMetaDatabase &&rhs) {
ContentMetaDatabase(std::move(rhs)).swap(*this);
return *this;
}
void swap(ContentMetaDatabase &rhs) {
std::swap(m_interface, rhs.m_interface);
}
public:
Result Set(const ContentMetaKey &key, const void *buf, size_t size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Set(key, sf::InBuffer(buf, size)));
}
Result Get(size_t *out_size, void *dst, size_t dst_size, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
u64 size;
R_TRY(m_interface->Get(std::addressof(size), key, sf::OutBuffer(dst, dst_size)));
*out_size = size;
R_SUCCEED();
}
#define AMS_NCM_DEFINE_GETTERS(Kind, IdType) \
Result Get##Kind(ContentId *out, IdType##Id id, u32 version) { \
R_RETURN(m_interface->GetContentIdByType(out, ContentMetaKey::MakeUnknownType(id.value, version), ContentType::Kind)); \
} \
\
Result Get##Kind(ContentInfo *out, IdType##Id id, u32 version) { \
R_RETURN(m_interface->GetContentInfoByType(out, ContentMetaKey::MakeUnknownType(id.value, version), ContentType::Kind)); \
} \
\
Result GetLatest##Kind(ContentId *out, IdType##Id id) { \
ContentMetaKey latest_key; \
R_TRY(m_interface->GetLatestContentMetaKey(std::addressof(latest_key), id.value)); \
R_RETURN(m_interface->GetContentIdByType(out, latest_key, ContentType::Kind)); \
} \
\
Result GetLatest##Kind(ContentInfo *out, IdType##Id id) { \
ContentMetaKey latest_key; \
R_TRY(m_interface->GetLatestContentMetaKey(std::addressof(latest_key), id.value)); \
R_RETURN(m_interface->GetContentInfoByType(out, latest_key, ContentType::Kind)); \
}
AMS_NCM_DEFINE_GETTERS(Program, Program)
AMS_NCM_DEFINE_GETTERS(Data, Data)
AMS_NCM_DEFINE_GETTERS(Control, Application)
AMS_NCM_DEFINE_GETTERS(HtmlDocument, Application)
AMS_NCM_DEFINE_GETTERS(LegalInformation, Application)
#undef AMS_NCM_DEFINE_GETTERS
Result Remove(const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Remove(key));
}
Result Remove(SystemProgramId id, u32 version) {
R_RETURN(this->Remove(ContentMetaKey::Make(id, version)));
}
Result Remove(SystemDataId id, u32 version) {
R_RETURN(this->Remove(ContentMetaKey::Make(id, version)));
}
Result Remove(ApplicationId id, u32 version) {
R_RETURN(this->Remove(ContentMetaKey::Make(id, version)));
}
Result GetContentIdByType(ContentId *out_content_id, const ContentMetaKey &key, ContentType type) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentIdByType(out_content_id, key, type));
}
Result GetContentIdByTypeAndIdOffset(ContentId *out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentIdByTypeAndIdOffset(out_content_id, key, type, id_offset));
}
ListCount ListApplication(ApplicationContentMetaKey *dst, size_t dst_size) {
ListCount lc = {};
R_ABORT_UNLESS(m_interface->ListApplication(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ApplicationContentMetaKey>(dst, dst_size), ContentMetaType::Unknown));
return lc;
}
ListCount ListContentMeta(ContentMetaKey *dst, size_t dst_size, ContentMetaType type = ContentMetaType::Unknown, ApplicationId app_id = InvalidApplicationId, u64 min = std::numeric_limits<u64>::min(), u64 max = std::numeric_limits<u64>::max(), ContentInstallType install_type = ContentInstallType::Full) {
ListCount lc = {};
R_ABORT_UNLESS(m_interface->List(std::addressof(lc.total), std::addressof(lc.written), sf::OutArray<ContentMetaKey>(dst, dst_size), type, app_id, min, max, install_type));
return lc;
}
Result GetLatest(ContentMetaKey *out_key, u64 id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetLatestContentMetaKey(out_key, id));
}
Result ListContentInfo(s32 *out_count, ContentInfo *dst, size_t dst_size, const ContentMetaKey &key, s32 offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->ListContentInfo(out_count, sf::OutArray<ContentInfo>(dst, dst_size), key, offset));
}
Result ListContentMetaInfo(s32 *out_count, ContentMetaInfo *dst, size_t dst_size, const ContentMetaKey &key, s32 offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->ListContentMetaInfo(out_count, sf::OutArray<ContentMetaInfo>(dst, dst_size), key, offset));
}
Result Has(bool *out, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Has(out, key));
}
Result HasAll(bool *out, const ContentMetaKey *keys, size_t num_keys) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->HasAll(out, sf::InArray<ContentMetaKey>(keys, num_keys)));
}
Result HasContent(bool *out, const ContentMetaKey &key, const ContentId &content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->HasContent(out, key, content_id));
}
Result GetSize(size_t *out_size, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
u64 size;
R_TRY(m_interface->GetSize(std::addressof(size), key));
*out_size = size;
R_SUCCEED();
}
Result GetRequiredSystemVersion(u32 *out_version, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetRequiredSystemVersion(out_version, key));
}
Result GetPatchId(PatchId *out_patch_id, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
static_assert(sizeof(*out_patch_id) == sizeof(u64));
R_RETURN(m_interface->GetPatchContentMetaId(reinterpret_cast<u64 *>(out_patch_id), key));
}
Result GetDataPatchId(DataPatchId *out_patch_id, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
static_assert(sizeof(*out_patch_id) == sizeof(u64));
R_RETURN(m_interface->GetPatchContentMetaId(reinterpret_cast<u64 *>(out_patch_id), key));
}
Result DisableForcibly() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->DisableForcibly());
}
Result LookupOrphanContent(bool *out_orphaned, ContentId *content_list, size_t count) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->LookupOrphanContent(sf::OutArray<bool>(out_orphaned, count), sf::InArray<ContentId>(content_list, count)));
}
Result Commit() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Commit());
}
Result GetAttributes(u8 *out_attributes, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetAttributes(out_attributes, key));
}
Result GetRequiredApplicationVersion(u32 *out_version, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetRequiredApplicationVersion(out_version, key));
}
Result GetContentAccessibilities(u8 *out_accessibilities, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentAccessibilities(out_accessibilities, key));
}
Result GetContentInfoByType(ContentInfo *out_content_info, const ContentMetaKey &key, ContentType type) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentInfoByType(out_content_info, key, type));
}
Result GetContentInfoByTypeAndIdOffset(ContentInfo *out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentInfoByTypeAndIdOffset(out_content_info, key, type, id_offset));
}
Result GetPlatform(ContentMetaPlatform *out, const ContentMetaKey &key) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetPlatform(out, key));
}
Result HasAttributes(u8 *out, u8 attr_mask) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->HasAttributes(out, attr_mask));
}
};
}

View File

@@ -1,857 +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/ncm/ncm_content_info.hpp>
#include <stratosphere/ncm/ncm_content_meta_id.hpp>
#include <stratosphere/ncm/ncm_content_meta.hpp>
#include <stratosphere/ncm/ncm_firmware_variation.hpp>
#include <stratosphere/ncm/ncm_mapped_memory.hpp>
namespace ams::ncm {
enum class UpdateType : u8 {
ApplyAsDelta = 0,
Overwrite = 1,
Create = 2,
};
struct FragmentIndicator {
u16 content_info_index;
u16 fragment_index;
};
struct FragmentSet {
ContentId source_content_id;
ContentId destination_content_id;
u32 source_size_low;
u16 source_size_high;
u16 destination_size_high;
u32 destination_size_low;
u16 fragment_count;
ContentType target_content_type;
UpdateType update_type;
u8 reserved[4];
constexpr s64 GetSourceSize() const {
return (static_cast<s64>(this->source_size_high) << 32) + this->source_size_low;
}
constexpr s64 GetDestinationSize() const {
return (static_cast<s64>(this->destination_size_high) << 32) + this->destination_size_low;
}
constexpr void SetSourceSize(s64 size) {
this->source_size_low = size & 0xFFFFFFFFll;
this->source_size_high = static_cast<u16>(size >> 32);
}
constexpr void SetDestinationSize(s64 size) {
this->destination_size_low = size & 0xFFFFFFFFll;
this->destination_size_high = static_cast<u16>(size >> 32);
}
};
struct SystemUpdateMetaExtendedDataHeader {
u32 version;
u32 firmware_variation_count;
};
struct DeltaMetaExtendedDataHeader {
PatchId source_id;
PatchId destination_id;
u32 source_version;
u32 destination_version;
u16 fragment_set_count;
u8 reserved[6];
};
struct PatchMetaExtendedDataHeader {
u32 history_count;
u32 delta_history_count;
u32 delta_count;
u32 fragment_set_count;
u32 history_content_total_count;
u32 delta_content_total_count;
u8 reserved[4];
};
struct PatchHistoryHeader {
ContentMetaKey key;
Digest digest;
u16 content_count;
u8 reserved[2];
};
struct PatchDeltaHistory {
PatchId source_id;
PatchId destination_id;
u32 source_version;
u32 destination_version;
u64 download_size;
u8 reserved[4];
};
struct PatchDeltaHeader {
DeltaMetaExtendedDataHeader delta;
u16 content_count;
u8 reserved[4];
};
template<typename MemberTypePointer, typename DataTypePointer>
class PatchMetaExtendedDataReaderWriterBase {
private:
MemberTypePointer m_data;
const size_t m_size;
public:
PatchMetaExtendedDataReaderWriterBase(MemberTypePointer d, size_t sz) : m_data(d), m_size(sz) { /* ... */ }
protected:
s32 CountFragmentSet(s32 delta_index) const {
auto delta_header = this->GetPatchDeltaHeader(0);
s32 count = 0;
for (s32 i = 0; i < delta_index; i++) {
count += delta_header[i].delta.fragment_set_count;
}
return count;
}
s32 CountHistoryContent(s32 history_index) const {
auto history_header = this->GetPatchHistoryHeader(0);
s32 count = 0;
for (s32 i = 0; i < history_index; i++) {
count += history_header[i].content_count;
}
return count;
}
s32 CountDeltaContent(s32 delta_index) const {
auto delta_header = this->GetPatchDeltaHeader(0);
s32 count = 0;
for (s32 i = 0; i < delta_index; i++) {
count += delta_header[i].content_count;
}
return count;
}
s32 CountFragment(s32 index) const {
auto fragment_set = this->GetFragmentSet(0, 0);
s32 count = 0;
for (s32 i = 0; i < index; i++) {
count += fragment_set[i].fragment_count;
}
return count;
}
DataTypePointer GetHeaderAddress() const {
return reinterpret_cast<DataTypePointer>(m_data);
}
DataTypePointer GetPatchHistoryHeaderAddress(s32 index) const {
auto header = this->GetHeader();
AMS_ABORT_UNLESS(static_cast<u16>(index) < header->history_count);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * index;
}
DataTypePointer GetPatchDeltaHistoryAddress(s32 index) const {
auto header = this->GetHeader();
AMS_ABORT_UNLESS(static_cast<u16>(index) < header->delta_history_count);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * index;
}
DataTypePointer GetPatchDeltaHeaderAddress(s32 index) const {
auto header = this->GetHeader();
AMS_ABORT_UNLESS(static_cast<u16>(index) < header->delta_count);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * header->delta_history_count
+ sizeof(PatchDeltaHeader) * index;
}
DataTypePointer GetFragmentSetAddress(s32 delta_index, s32 fragment_set_index) const {
auto header = this->GetHeader();
AMS_ABORT_UNLESS(static_cast<u16>(delta_index) < header->delta_count);
auto delta_header = this->GetPatchDeltaHeader(delta_index);
AMS_ABORT_UNLESS(static_cast<u16>(fragment_set_index) < delta_header->delta.fragment_set_count);
auto previous_fragment_set_count = this->CountFragmentSet(delta_index);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * header->delta_history_count
+ sizeof(PatchDeltaHeader) * header->delta_count
+ sizeof(FragmentSet) * (previous_fragment_set_count + fragment_set_index);
}
DataTypePointer GetPatchHistoryContentInfoAddress(s32 history_index, s32 content_index) const {
auto header = this->GetHeader();
auto history_header = this->GetPatchHistoryHeader(history_index);
AMS_ABORT_UNLESS(static_cast<u16>(content_index) < history_header->content_count);
auto prev_history_count = this->CountHistoryContent(history_index);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * header->delta_history_count
+ sizeof(PatchDeltaHeader) * header->delta_count
+ sizeof(FragmentSet) * header->fragment_set_count
+ sizeof(ContentInfo) * (prev_history_count + content_index);
}
DataTypePointer GetPatchDeltaPackagedContentInfoAddress(s32 delta_index, s32 content_index) const {
auto header = this->GetHeader();
auto delta_header = this->GetPatchDeltaHeader(delta_index);
AMS_ABORT_UNLESS(static_cast<u16>(content_index) < delta_header->content_count);
auto content_count = this->CountDeltaContent(delta_index);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * header->delta_history_count
+ sizeof(PatchDeltaHeader) * header->delta_count
+ sizeof(FragmentSet) * header->fragment_set_count
+ sizeof(ContentInfo) * header->history_content_total_count
+ sizeof(PackagedContentInfo) * (content_count + content_index);
}
DataTypePointer GetFragmentIndicatorAddress(s32 delta_index, s32 fragment_set_index, s32 index) const {
auto header = this->GetHeader();
auto fragment_set = this->GetFragmentSet(delta_index, fragment_set_index);
AMS_ABORT_UNLESS(static_cast<u16>(index) < fragment_set->fragment_count);
auto fragment_set_count = this->CountFragmentSet(delta_index);
auto fragment_count = this->CountFragment(fragment_set_count + fragment_set_index);
return this->GetHeaderAddress()
+ sizeof(PatchMetaExtendedDataHeader)
+ sizeof(PatchHistoryHeader) * header->history_count
+ sizeof(PatchDeltaHistory) * header->delta_history_count
+ sizeof(PatchDeltaHeader) * header->delta_count
+ sizeof(FragmentSet) * header->fragment_set_count
+ sizeof(ContentInfo) * header->history_content_total_count
+ sizeof(PackagedContentInfo) * header->delta_content_total_count
+ sizeof(FragmentIndicator) * (fragment_count + index);
}
public:
const PatchMetaExtendedDataHeader *GetHeader() const {
return reinterpret_cast<const PatchMetaExtendedDataHeader *>(this->GetHeaderAddress());
}
const PatchHistoryHeader *GetPatchHistoryHeader(s32 index) const {
return reinterpret_cast<const PatchHistoryHeader *>(this->GetPatchHistoryHeaderAddress(index));
}
const PatchDeltaHistory *GetPatchDeltaHistory(s32 index) const {
return reinterpret_cast<const PatchDeltaHistory *>(this->GetPatchDeltaHistoryAddress(index));
}
const ContentInfo *GetPatchHistoryContentInfo(s32 history_index, s32 content_index) const {
return reinterpret_cast<const ContentInfo *>(this->GetPatchHistoryContentInfoAddress(history_index, content_index));
}
const PatchDeltaHeader *GetPatchDeltaHeader(s32 index) const {
return reinterpret_cast<const PatchDeltaHeader *>(this->GetPatchDeltaHeaderAddress(index));
}
const PackagedContentInfo *GetPatchDeltaPackagedContentInfo(s32 delta_index, s32 content_index) const {
return reinterpret_cast<const PackagedContentInfo *>(this->GetPatchDeltaPackagedContentInfoAddress(delta_index, content_index));
}
const FragmentSet *GetFragmentSet(s32 delta_index, s32 fragment_set_index) const {
return reinterpret_cast<const FragmentSet *>(this->GetFragmentSetAddress(delta_index, fragment_set_index));
}
const FragmentIndicator *GetFragmentIndicator(s32 delta_index, s32 fragment_set_index, s32 index) const {
return reinterpret_cast<const FragmentIndicator *>(this->GetFragmentIndicatorAddress(delta_index, fragment_set_index, index));
}
const FragmentIndicator *FindFragmentIndicator(s32 delta_index, s32 fragment_set_index, s32 fragment_index) const {
auto fragment_set = this->GetFragmentSet(delta_index, fragment_set_index);
auto fragment = this->GetFragmentIndicator(delta_index, fragment_set_index, 0);
for (s32 i = 0; i < fragment_set->fragment_count; i++) {
if (fragment[i].fragment_index == fragment_index) {
return std::addressof(fragment[i]);
}
}
return nullptr;
}
};
class PatchMetaExtendedDataReader : public PatchMetaExtendedDataReaderWriterBase<const void *, const u8 *> {
public:
PatchMetaExtendedDataReader(const void *data, size_t size) : PatchMetaExtendedDataReaderWriterBase(data, size) { /* ... */ }
};
class SystemUpdateMetaExtendedDataReaderWriterBase {
private:
void *m_data;
const size_t m_size;
bool m_is_header_valid;
protected:
constexpr SystemUpdateMetaExtendedDataReaderWriterBase(const void *d, size_t sz) : m_data(const_cast<void *>(d)), m_size(sz), m_is_header_valid(true) { /* ... */ }
constexpr SystemUpdateMetaExtendedDataReaderWriterBase(void *d, size_t sz) : m_data(d), m_size(sz), m_is_header_valid(false) { /* ... */ }
uintptr_t GetHeaderAddress() const {
return reinterpret_cast<uintptr_t>(m_data);
}
uintptr_t GetFirmwareVariationIdStartAddress() const {
return this->GetHeaderAddress() + sizeof(SystemUpdateMetaExtendedDataHeader);
}
uintptr_t GetFirmwareVariationIdAddress(size_t i) const {
return this->GetFirmwareVariationIdStartAddress() + i * sizeof(FirmwareVariationId);
}
uintptr_t GetFirmwareVariationInfoStartAddress() const {
return this->GetFirmwareVariationIdAddress(this->GetFirmwareVariationCount());
}
uintptr_t GetFirmwareVariationInfoAddress(size_t i) const {
return this->GetFirmwareVariationInfoStartAddress() + i * sizeof(FirmwareVariationInfo);
}
uintptr_t GetContentMetaInfoStartAddress() const {
return this->GetFirmwareVariationInfoAddress(this->GetFirmwareVariationCount());
}
uintptr_t GetContentMetaInfoAddress(size_t i) const {
return this->GetContentMetaInfoStartAddress() + i * sizeof(ContentMetaInfo);
}
public:
const SystemUpdateMetaExtendedDataHeader *GetHeader() const {
AMS_ABORT_UNLESS(m_is_header_valid);
return reinterpret_cast<const SystemUpdateMetaExtendedDataHeader *>(this->GetHeaderAddress());
}
size_t GetFirmwareVariationCount() const {
return this->GetHeader()->firmware_variation_count;
}
const FirmwareVariationId *GetFirmwareVariationId(size_t i) const {
AMS_ABORT_UNLESS(i < this->GetFirmwareVariationCount());
return reinterpret_cast<FirmwareVariationId *>(this->GetFirmwareVariationIdAddress(i));
}
const FirmwareVariationInfo *GetFirmwareVariationInfo(size_t i) const {
AMS_ABORT_UNLESS(i < this->GetFirmwareVariationCount());
return reinterpret_cast<FirmwareVariationInfo *>(this->GetFirmwareVariationInfoAddress(i));
}
void GetContentMetaInfoList(Span<const ContentMetaInfo> *out_list, size_t i) const {
size_t preceding_content_meta_count = 0;
/* Count the number of preceding content metas. */
for (size_t j = 0; j < i; j++) {
preceding_content_meta_count += this->GetFirmwareVariationInfo(j)->content_meta_count;
}
/* Output the list. */
*out_list = Span<const ContentMetaInfo>(reinterpret_cast<const ContentMetaInfo *>(this->GetContentMetaInfoAddress(preceding_content_meta_count)), this->GetFirmwareVariationInfo(i)->content_meta_count);
}
};
class SystemUpdateMetaExtendedDataReader : public SystemUpdateMetaExtendedDataReaderWriterBase {
public:
constexpr SystemUpdateMetaExtendedDataReader(const void *data, size_t size) : SystemUpdateMetaExtendedDataReaderWriterBase(data, size) { /* ... */ }
};
template<typename T>
class ReadableStructPin;
class AccessorBase {
public:
template<typename T>
class PinBase {
private:
AccessorBase *m_accessor;
u64 m_pin_id;
T *m_data;
size_t m_size;
public:
PinBase() : m_accessor(nullptr), m_data(nullptr), m_size(0) {
/* ... */
}
PinBase(const PinBase &) = delete;
PinBase &operator=(const PinBase &) = delete;
PinBase(PinBase &&rhs) : m_accessor(rhs.m_accessor), m_pin_id(rhs.m_pin_id), m_data(rhs.m_data), m_size(rhs.m_size) {
rhs.m_accessor = nullptr;
}
PinBase &operator=(PinBase &&rhs) {
m_accessor = rhs.m_accessor;
m_pin_id = rhs.m_pin_id;
m_data = rhs.m_data;
m_size = rhs.m_size;
rhs.m_accessor = nullptr;
return *this;
}
virtual ~PinBase() {
this->Reset();
}
public:
void Reset() {
if (m_accessor != nullptr) {
m_accessor->ReleasePin(m_pin_id);
m_accessor = nullptr;
}
}
void Reset(AccessorBase *accessor, u64 pin_id, void *data, size_t size) {
AMS_ASSERT(data != nullptr || size == 0);
this->Reset();
m_accessor = accessor;
m_pin_id = pin_id;
m_data = reinterpret_cast<T *>(data);
m_size = size;
}
T *GetData() const {
return m_data;
}
size_t GetDataSize() const {
return m_size;
}
};
private:
IMapper *m_mapper;
public:
AccessorBase(IMapper *mapper) : m_mapper(mapper) {
/* ... */
}
template<typename T>
Result AcquireReadableStructPin(ReadableStructPin<T> *out, size_t offset) {
/* Acquire mapped memory for the pin. */
MappedMemory memory = {};
R_TRY(m_mapper->GetMappedMemory(std::addressof(memory), offset, sizeof(T)));
/* Mark the memory as in use. */
R_RETURN(m_mapper->MarkUsing(memory.id));
/* Setup the pin. */
out->Reset(this, memory.id, memory.GetBuffer(offset, sizeof(T)), sizeof(T));
R_SUCCEED();
}
Result ReleasePin(u64 id) {
R_RETURN(m_mapper->UnmarkUsing(id));
}
template<typename T>
Result ReadStruct(T *out, size_t offset) {
/* Acquire mapped memory for the pin. */
MappedMemory memory = {};
R_TRY(m_mapper->GetMappedMemory(std::addressof(memory), offset, sizeof(T)));
/* Mark the memory as in use. */
R_RETURN(m_mapper->MarkUsing(memory.id));
ON_SCOPE_EXIT { this->ReleasePin(memory.id); };
/* Copy out the struct. */
*out = *reinterpret_cast<const T *>(memory.GetBuffer(offset, sizeof(T)));
R_SUCCEED();
}
};
template<typename T>
class ReadableStructPin final : public AccessorBase::PinBase<const u8> {
public:
using PinBase::PinBase;
using PinBase::operator=;
const T *Get() const {
return reinterpret_cast<const T *>(this->GetData());
}
size_t GetSize() const {
return this->GetDataSize();
}
const T &operator*() const { return *this->Get(); }
const T *operator->() const { return this->Get(); }
};
class PatchMetaExtendedDataAccessor : public AccessorBase {
private:
struct CachedCount {
s32 index;
s32 count;
};
private:
util::optional<CachedCount> m_cached_history_content_count = util::nullopt;
util::optional<CachedCount> m_cached_delta_content_count = util::nullopt;
util::optional<CachedCount> m_cached_fragment_set_count = util::nullopt;
util::optional<CachedCount> m_cached_fragment_indicator_count = util::nullopt;
util::optional<PatchMetaExtendedDataHeader> m_header = util::nullopt;
public:
using AccessorBase::AccessorBase;
public:
Result GetHeader(ReadableStructPin<PatchMetaExtendedDataHeader> *out) { R_RETURN(this->AcquireReadableStructPin(out, 0)); }
Result GetHeader(PatchMetaExtendedDataHeader *out) { R_RETURN(this->template ReadStruct<PatchMetaExtendedDataHeader>(out, 0)); }
Result GetHistoryHeader(ReadableStructPin<PatchHistoryHeader> *out, s32 index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= index && static_cast<u32>(index) < m_header->history_count, ncm::ResultInvalidOffset());
/* Get the header. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * index;
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetPatchDeltaHistory(ReadableStructPin<PatchDeltaHistory> *out, s32 index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= index && static_cast<u32>(index) < m_header->delta_history_count, ncm::ResultInvalidOffset());
/* Get the history. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * index;
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetPatchDeltaHeader(ReadableStructPin<PatchDeltaHeader> *out, s32 index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= index && static_cast<u32>(index) < m_header->delta_count, ncm::ResultInvalidOffset());
/* Get the header. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * index;
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetFragmentSet(ReadableStructPin<FragmentSet> *out, s32 delta_index, s32 fragment_set_index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= delta_index && static_cast<u32>(delta_index) < m_header->delta_count, ncm::ResultInvalidOffset());
/* Get the previous fragment set count. */
s32 previous_fragment_set_count = 0;
R_TRY(this->CountFragmentSet(std::addressof(previous_fragment_set_count), delta_index));
/* Get the set. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * (previous_fragment_set_count + fragment_set_index);
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetFragmentSetDirectly(ReadableStructPin<FragmentSet> *out, s32 fragment_set_direct_index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= fragment_set_direct_index && static_cast<u32>(fragment_set_direct_index) < m_header->fragment_set_count, ncm::ResultInvalidOffset());
/* Get the set. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * (fragment_set_direct_index);
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetPatchHistoryContentInfo(ReadableStructPin<ContentInfo> *out, s32 history_index, s32 content_index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= history_index && static_cast<u32>(history_index) < m_header->history_count, ncm::ResultInvalidOffset());
/* Determine the true history content index. */
s32 prev_history_count = 0;
R_TRY(this->CountHistoryContentInfo(std::addressof(prev_history_count), history_index));
/* Adjust and check the content index. */
content_index += prev_history_count;
R_UNLESS(0 <= content_index && static_cast<u32>(content_index) < m_header->history_content_total_count, ncm::ResultInvalidOffset());
/* Get the info. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * m_header->fragment_set_count + sizeof(ContentInfo) * content_index;
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetPatchDeltaContentInfo(ReadableStructPin<PackagedContentInfo> *out, s32 delta_index, s32 content_index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= delta_index && static_cast<u32>(delta_index) < m_header->delta_count, ncm::ResultInvalidOffset());
/* Determine the true delta content index. */
s32 prev_delta_count = 0;
R_TRY(this->CountDeltaContentInfo(std::addressof(prev_delta_count), delta_index));
/* Adjust and check the content index. */
content_index += prev_delta_count;
R_UNLESS(0 <= content_index && static_cast<u32>(content_index) < m_header->delta_content_total_count, ncm::ResultInvalidOffset());
/* Get the info. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * m_header->fragment_set_count + sizeof(ContentInfo) * m_header->history_content_total_count + sizeof(PackagedContentInfo) * content_index;
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result GetFragmentIndicator(ReadableStructPin<FragmentIndicator> *out, s32 delta_index, s32 fragment_set_index, s32 index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= delta_index && static_cast<u32>(delta_index) < m_header->delta_count, ncm::ResultInvalidOffset());
/* Get the previous fragment set count. */
s32 previous_fragment_set_count = 0;
R_TRY(this->CountFragmentSet(std::addressof(previous_fragment_set_count), delta_index));
/* Get the previous fragment indicator count. */
s32 previous_fragment_count = 0;
R_TRY(this->CountFragmentIndicator(std::addressof(previous_fragment_count), previous_fragment_count + fragment_set_index));
/* Get the info. */
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * m_header->fragment_set_count + sizeof(ContentInfo) * m_header->history_content_total_count + sizeof(PackagedContentInfo) * m_header->delta_content_total_count + sizeof(FragmentIndicator) * (previous_fragment_count + index);
R_RETURN(this->AcquireReadableStructPin(out, offset));
}
Result FindFragmentIndicator(ReadableStructPin<FragmentIndicator> *out, s32 delta_index, s32 fragment_set_index, s32 fragment_index) {
/* Ensure we have our header. */
R_TRY(this->EnsureHeader());
/* Check that the index is valid. */
R_UNLESS(0 <= delta_index && static_cast<u32>(delta_index) < m_header->delta_count, ncm::ResultInvalidOffset());
/* Get the fragment count. */
s32 fragment_count = 0;
{
ReadableStructPin<FragmentSet> set;
R_TRY(this->GetFragmentSet(std::addressof(set), delta_index, fragment_set_index));
fragment_count = set->fragment_count;
}
/* Get the previous fragment set count. */
s32 previous_fragment_set_count = 0;
R_TRY(this->CountFragmentSet(std::addressof(previous_fragment_set_count), delta_index));
/* Get the previous fragment indicator count. */
s32 previous_fragment_count = 0;
R_TRY(this->CountFragmentIndicator(std::addressof(previous_fragment_count), previous_fragment_count + fragment_set_index));
/* Look for a correct indicator. */
for (auto i = 0; i < fragment_count; ++i) {
/* Get the current info. */
ReadableStructPin<FragmentIndicator> indicator;
const size_t offset = sizeof(PatchHistoryHeader) + sizeof(PatchHistoryHeader) * m_header->history_count + sizeof(PatchDeltaHistory) * m_header->delta_history_count + sizeof(PatchDeltaHeader) * m_header->delta_count + sizeof(FragmentSet) * m_header->fragment_set_count + sizeof(ContentInfo) * m_header->history_content_total_count + sizeof(PackagedContentInfo) * m_header->delta_content_total_count + sizeof(FragmentIndicator) * (previous_fragment_count + i);
R_TRY(this->AcquireReadableStructPin(std::addressof(indicator), offset));
/* If it matches, return it. */
if (indicator->fragment_index == fragment_index) {
*out = std::move(indicator);
R_SUCCEED();
}
}
/* We didn't find an indicator. */
R_THROW(ncm::ResultFragmentIndicatorNotFound());
}
Result GetHistoryHeader(PatchHistoryHeader *out, s32 index) {
/* Get the pin. */
ReadableStructPin<PatchHistoryHeader> pin;
R_TRY(this->GetHistoryHeader(std::addressof(pin), index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetPatchDeltaHistory(PatchDeltaHistory *out, s32 index) {
/* Get the pin. */
ReadableStructPin<PatchDeltaHistory> pin;
R_TRY(this->GetPatchDeltaHistory(std::addressof(pin), index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetPatchDeltaHeader(PatchDeltaHeader *out, s32 index) {
/* Get the pin. */
ReadableStructPin<PatchDeltaHeader> pin;
R_TRY(this->GetPatchDeltaHeader(std::addressof(pin), index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetFragmentSet(FragmentSet *out, s32 delta_index, s32 fragment_set_index) {
/* Get the pin. */
ReadableStructPin<FragmentSet> pin;
R_TRY(this->GetFragmentSet(std::addressof(pin), delta_index, fragment_set_index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetPatchHistoryContentInfo(ContentInfo *out, s32 history_index, s32 content_index) {
/* Get the header. */
ReadableStructPin<ContentInfo> pin;
R_TRY(this->GetPatchHistoryContentInfo(std::addressof(pin), history_index, content_index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetPatchDeltaContentInfo(PackagedContentInfo *out, s32 delta_index, s32 content_index) {
/* Get the header. */
ReadableStructPin<PackagedContentInfo> pin;
R_TRY(this->GetPatchDeltaContentInfo(std::addressof(pin), delta_index, content_index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result GetFragmentIndicator(FragmentIndicator *out, s32 delta_index, s32 fragment_set_index, s32 index) {
/* Get the header. */
ReadableStructPin<FragmentIndicator> pin;
R_TRY(this->GetFragmentIndicator(std::addressof(pin), delta_index, fragment_set_index, index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result FindFragmentIndicator(FragmentIndicator *out, s32 delta_index, s32 fragment_set_index, s32 fragment_index) {
/* Get the header. */
ReadableStructPin<FragmentIndicator> pin;
R_TRY(this->FindFragmentIndicator(std::addressof(pin), delta_index, fragment_set_index, fragment_index));
/* Copy it out. */
*out = *pin;
R_SUCCEED();
}
Result CountHistoryContentInfo(s32 *out, s32 index) {
R_RETURN(this->CountImpl(out, index, m_cached_history_content_count, [&](s32 *out, s32 i) -> Result {
/* Get the history header. */
ReadableStructPin<ncm::PatchHistoryHeader> header;
R_TRY(this->GetHistoryHeader(std::addressof(header), i));
/* Set the content count. */
*out = header->content_count;
R_SUCCEED();
}));
}
Result CountDeltaContentInfo(s32 *out, s32 index) {
R_RETURN(this->CountImpl(out, index, m_cached_delta_content_count, [&](s32 *out, s32 i) -> Result {
/* Get the history header. */
ReadableStructPin<ncm::PatchDeltaHeader> header;
R_TRY(this->GetPatchDeltaHeader(std::addressof(header), i));
/* Set the content count. */
*out = header->content_count;
R_SUCCEED();
}));
}
Result CountFragmentSet(s32 *out, s32 index) {
R_RETURN(this->CountImpl(out, index, m_cached_fragment_set_count, [&](s32 *out, s32 i) -> Result {
/* Get the history header. */
ReadableStructPin<ncm::PatchDeltaHeader> header;
R_TRY(this->GetPatchDeltaHeader(std::addressof(header), i));
/* Set the fragment set count. */
*out = header->delta.fragment_set_count;
R_SUCCEED();
}));
}
Result CountFragmentIndicator(s32 *out, s32 index) {
R_RETURN(this->CountImpl(out, index, m_cached_fragment_indicator_count, [&](s32 *out, s32 i) -> Result {
/* Get the history header. */
ReadableStructPin<ncm::FragmentSet> set;
R_TRY(this->GetFragmentSetDirectly(std::addressof(set), i));
/* Set the indicator count. */
*out = set->fragment_count;
R_SUCCEED();
}));
}
private:
Result CountImpl(s32 *out, s32 index, util::optional<CachedCount> &cache, auto get_count_impl) const {
/* Ensure the value is cached. */
if (!(cache.has_value() && cache->index == index)) {
/* Determine the count. */
CachedCount calc = { .index = index, .count = 0 };
for (auto i = 0; i < index; ++i) {
s32 cur_count = 0;
R_TRY(get_count_impl(std::addressof(cur_count), i));
calc.count += cur_count;
}
/* Cache the count. */
cache = calc;
}
/* Set the output count. */
*out = cache->count;
R_SUCCEED();
}
private:
Result EnsureHeader() {
/* If we have our header, we're good. */
R_SUCCEED_IF(m_header.has_value());
/* Get our header. */
PatchMetaExtendedDataHeader header{};
R_TRY(this->GetHeader(std::addressof(header)));
/* Set our header. */
m_header.emplace(header);
R_SUCCEED();
}
};
}

View File

@@ -1,101 +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/ncm/ncm_data_id.hpp>
#include <stratosphere/ncm/ncm_program_id.hpp>
namespace ams::ncm {
struct ApplicationId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const ApplicationId &) const = default;
constexpr inline bool operator!=(const ApplicationId &) const = default;
static const ApplicationId Start;
static const ApplicationId End;
};
constexpr inline const ApplicationId InvalidApplicationId = {};
inline constexpr const ApplicationId ApplicationId::Start = { 0x0100000000010000ul };
inline constexpr const ApplicationId ApplicationId::End = { 0x01FFFFFFFFFFFFFFul };
inline constexpr bool IsApplicationId(const ProgramId &program_id) {
return ApplicationId::Start <= program_id && program_id <= ApplicationId::End;
}
inline constexpr bool IsApplicationId(const ApplicationId &) {
return true;
}
struct ApplicationGroupId {
u64 value;
};
struct PatchId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const PatchId &) const = default;
constexpr inline bool operator!=(const PatchId &) const = default;
};
struct PatchGroupId {
u64 value;
};
struct AddOnContentId {
u64 value;
constexpr operator DataId() const {
return { this->value };
}
constexpr inline bool operator==(const AddOnContentId &) const = default;
constexpr inline bool operator!=(const AddOnContentId &) const = default;
};
struct DeltaId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const DeltaId &) const = default;
constexpr inline bool operator!=(const DeltaId &) const = default;
};
struct DataPatchId {
u64 value;
constexpr operator DataId() const {
return { this->value };
}
constexpr inline bool operator==(const DataPatchId &) const = default;
constexpr inline bool operator!=(const DataPatchId &) const = default;
};
}

View File

@@ -1,114 +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 <vapours.hpp>
#include <stratosphere/ncm/ncm_content_meta_id.hpp>
#include <stratosphere/ncm/ncm_content_meta_type.hpp>
#include <stratosphere/ncm/ncm_system_content_meta_id.hpp>
namespace ams::ncm {
enum class ContentInstallType : u8 {
Full = 0,
FragmentOnly = 1,
Unknown = 7,
};
struct ContentMetaKey {
u64 id;
u32 version;
ContentMetaType type;
ContentInstallType install_type;
u8 padding[2];
bool operator<(const ContentMetaKey &rhs) const {
return std::tie(this->id, this->version, this->type, this->install_type) < std::tie(rhs.id, rhs.version, rhs.type, rhs.install_type);
}
constexpr bool operator==(const ContentMetaKey &rhs) const {
return std::tie(this->id, this->version, this->type, this->install_type) == std::tie(rhs.id, rhs.version, rhs.type, rhs.install_type);
}
constexpr bool operator!=(const ContentMetaKey &rhs) const {
return !(*this == rhs);
}
static constexpr ContentMetaKey MakeUnknownType(u64 id, u32 version) {
return { .id = id, .version = version, .type = ContentMetaType::Unknown };
}
static constexpr ContentMetaKey Make(u64 id, u32 version, ContentMetaType type) {
return { .id = id, .version = version, .type = type };
}
static constexpr ContentMetaKey Make(u64 id, u32 version, ContentMetaType type, ContentInstallType install_type) {
return { .id = id, .version = version, .type = type, .install_type = install_type };
}
static constexpr ContentMetaKey Make(SystemProgramId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::SystemProgram };
}
static constexpr ContentMetaKey Make(SystemDataId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::SystemData };
}
static constexpr ContentMetaKey Make(SystemUpdateId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::SystemUpdate };
}
static constexpr ContentMetaKey Make(ApplicationId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::Application };
}
static constexpr ContentMetaKey Make(PatchId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::Patch };
}
static constexpr ContentMetaKey Make(PatchId id, u32 version, ContentInstallType install_type) {
return { .id = id.value, .version = version, .type = ContentMetaType::Patch, .install_type = install_type };
}
static constexpr ContentMetaKey Make(DeltaId id, u32 version) {
return { .id = id.value, .version = version, .type = ContentMetaType::Delta };
}
};
static_assert(sizeof(ContentMetaKey) == 0x10);
struct ApplicationContentMetaKey {
ContentMetaKey key;
ncm::ApplicationId application_id;
};
static_assert(sizeof(ApplicationContentMetaKey) == 0x18);
struct StorageContentMetaKey {
ContentMetaKey key;
StorageId storage_id;
u8 reserved[7];
constexpr bool operator==(StorageContentMetaKey &rhs) const {
return this->key == rhs.key && this->storage_id == rhs.storage_id;
}
constexpr bool operator<(StorageContentMetaKey &rhs) const {
return this->key == rhs.key ? this->storage_id < rhs.storage_id : this->key < rhs.key;
}
};
static_assert(sizeof(StorageContentMetaKey) == 0x18);
}

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 <vapours.hpp>
namespace ams::ncm {
enum class ContentMetaPlatform : u8 {
Nx = 0x0,
};
}

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 <vapours.hpp>
namespace ams::ncm {
enum class ContentMetaType : u8 {
Unknown = 0x0,
SystemProgram = 0x1,
SystemData = 0x2,
SystemUpdate = 0x3,
BootImagePackage = 0x4,
BootImagePackageSafe = 0x5,
Application = 0x80,
Patch = 0x81,
AddOnContent = 0x82,
Delta = 0x83,
DataPatch = 0x84,
};
const char *GetContentMetaTypeString(ContentMetaType type);
}

View File

@@ -1,45 +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/ncm/ncm_auto_buffer.hpp>
#include <stratosphere/ncm/ncm_storage_id.hpp>
#include <stratosphere/ncm/ncm_content_storage.hpp>
#include <stratosphere/ncm/ncm_content_meta_key.hpp>
#include <stratosphere/ncm/ncm_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_firmware_variation.hpp>
namespace ams::ncm {
using MountContentMetaFunction = Result (*)(const char *mount_name, const char *path, fs::ContentAttributes attr);
bool IsContentMetaFileName(const char *name);
Result ReadContentMetaPathAlongWithExtendedDataAndDigest(AutoBuffer *out, const char *path, fs::ContentAttributes attr);
Result ReadContentMetaPathAlongWithExtendedDataAndDigestSuppressingFsAbort(AutoBuffer *out, const char *path, fs::ContentAttributes attr);
Result ReadContentMetaPathWithoutExtendedDataOrDigest(AutoBuffer *out, const char *path, fs::ContentAttributes attr);
Result ReadContentMetaPathWithoutExtendedDataOrDigestSuppressingFsAbort(AutoBuffer *out, const char *path, fs::ContentAttributes attr);
using ReadContentMetaPathFunction = Result (*)(AutoBuffer *out, const char *path, fs::ContentAttributes attr);
Result TryReadContentMetaPath(fs::ContentAttributes *out_attr, AutoBuffer *out, const char *path, ReadContentMetaPathFunction func);
Result TryReadContentMetaPath(AutoBuffer *out, const char *path, ReadContentMetaPathFunction func);
Result ReadVariationContentMetaInfoList(s32 *out_count, std::unique_ptr<ContentMetaInfo[]> *out_meta_infos, const Path &path, fs::ContentAttributes attr, FirmwareVariationId firmware_variation_id);
void SetMountContentMetaFunction(MountContentMetaFunction func);
}

View File

@@ -1,217 +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/ncm/ncm_i_content_storage.hpp>
namespace ams::ncm {
class ContentStorage {
NON_COPYABLE(ContentStorage);
private:
sf::SharedPointer<IContentStorage> m_interface;
public:
ContentStorage() : m_interface(nullptr) { /* ... */ }
explicit ContentStorage(sf::SharedPointer<IContentStorage> intf) : m_interface(intf) { /* ... */ }
ContentStorage(ContentStorage &&rhs) {
m_interface = std::move(rhs.m_interface);
}
ContentStorage &operator=(ContentStorage &&rhs) {
ContentStorage(std::move(rhs)).swap(*this);
return *this;
}
void swap(ContentStorage &rhs) {
std::swap(m_interface, rhs.m_interface);
}
public:
PlaceHolderId GeneratePlaceHolderId() {
AMS_ASSERT(m_interface != nullptr);
PlaceHolderId id;
R_ABORT_UNLESS(m_interface->GeneratePlaceHolderId(std::addressof(id)));
return id;
}
Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->CreatePlaceHolder(placeholder_id, content_id, size));
}
Result DeletePlaceHolder(PlaceHolderId placeholder_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->DeletePlaceHolder(placeholder_id));
}
Result HasPlaceHolder(bool *out, PlaceHolderId placeholder_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->HasPlaceHolder(out, placeholder_id));
}
Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const void *buf, size_t size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->WritePlaceHolder(placeholder_id, offset, sf::InBuffer(buf, size)));
}
Result Register(PlaceHolderId placeholder_id, ContentId content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Register(placeholder_id, content_id));
}
Result Delete(ContentId content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Delete(content_id));
}
Result Has(bool *out, ContentId content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->Has(out, content_id));
}
void GetPath(Path *out, ContentId content_id) {
AMS_ASSERT(m_interface != nullptr);
R_ABORT_UNLESS(m_interface->GetPath(out, content_id));
}
void GetPlaceHolderPath(Path *out, PlaceHolderId placeholder_id) {
AMS_ASSERT(m_interface != nullptr);
R_ABORT_UNLESS(m_interface->GetPlaceHolderPath(out, placeholder_id));
}
Result CleanupAllPlaceHolder() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->CleanupAllPlaceHolder());
}
Result ListPlaceHolder(s32 *out_count, PlaceHolderId *out_list, size_t out_list_size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->ListPlaceHolder(out_count, sf::OutArray<PlaceHolderId>(out_list, out_list_size)));
}
Result GetContentCount(s32 *out_count) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetContentCount(out_count));
}
Result ListContentId(s32 *out_count, ContentId *out_list, size_t out_list_size, s32 offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->ListContentId(out_count, sf::OutArray<ContentId>(out_list, out_list_size), offset));
}
Result GetSize(s64 *out_size, ContentId content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetSizeFromContentId(out_size, content_id));
}
Result GetSize(s64 *out_size, PlaceHolderId placeholder_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetSizeFromPlaceHolderId(out_size, placeholder_id));
}
Result DisableForcibly() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->DisableForcibly());
}
Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->RevertToPlaceHolder(placeholder_id, old_content_id, new_content_id));
}
Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->SetPlaceHolderSize(placeholder_id, size));
}
Result ReadContentIdFile(void *dst, size_t size, ContentId content_id, s64 offset) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->ReadContentIdFile(sf::OutBuffer(dst, size), content_id, offset));
}
Result GetRightsId(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id, fs::ContentAttributes attr) {
AMS_ASSERT(m_interface != nullptr);
const auto vers = hos::GetVersion();
if (vers >= hos::Version_16_0_0) {
R_RETURN(m_interface->GetRightsIdFromPlaceHolderId(out_rights_id, placeholder_id, attr));
} else if (vers >= hos::Version_3_0_0) {
R_RETURN(m_interface->GetRightsIdFromPlaceHolderIdDeprecated2(out_rights_id, placeholder_id));
} else {
AMS_ABORT_UNLESS(vers >= hos::Version_2_0_0);
*out_rights_id = {};
R_RETURN(m_interface->GetRightsIdFromPlaceHolderIdDeprecated(std::addressof(out_rights_id->id), placeholder_id));
}
}
Result GetRightsId(ncm::RightsId *out_rights_id, ContentId content_id, fs::ContentAttributes attr) {
AMS_ASSERT(m_interface != nullptr);
const auto vers = hos::GetVersion();
if (vers >= hos::Version_16_0_0) {
R_RETURN(m_interface->GetRightsIdFromContentId(out_rights_id, content_id, attr));
} else if (vers >= hos::Version_3_0_0) {
R_RETURN(m_interface->GetRightsIdFromContentIdDeprecated2(out_rights_id, content_id));
} else {
AMS_ABORT_UNLESS(vers >= hos::Version_2_0_0);
*out_rights_id = {};
R_RETURN(m_interface->GetRightsIdFromContentIdDeprecated(std::addressof(out_rights_id->id), content_id));
}
}
Result WriteContentForDebug(ContentId content_id, s64 offset, const void *buf, size_t size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->WriteContentForDebug(content_id, offset, sf::InBuffer(buf, size)));
}
Result GetFreeSpaceSize(s64 *out_size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetFreeSpaceSize(out_size));
}
Result GetTotalSpaceSize(s64 *out_size) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetTotalSpaceSize(out_size));
}
Result FlushPlaceHolder() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->FlushPlaceHolder());
}
Result RepairInvalidFileAttribute() {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->RepairInvalidFileAttribute());
}
Result GetRightsIdFromPlaceHolderIdWithCache(ncm::RightsId *out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr) {
AMS_ASSERT(m_interface != nullptr);
const auto vers = hos::GetVersion();
if (vers >= hos::Version_16_0_0) {
R_RETURN(m_interface->GetRightsIdFromPlaceHolderIdWithCache(out_rights_id, placeholder_id, cache_content_id, attr));
} else {
R_RETURN(m_interface->GetRightsIdFromPlaceHolderIdWithCacheDeprecated(out_rights_id, cache_content_id, placeholder_id));
}
}
Result GetProgramId(ncm::ProgramId *out, ContentId content_id, fs::ContentAttributes attr) {
AMS_ASSERT(m_interface != nullptr);
R_RETURN(m_interface->GetProgramId(out, content_id, attr));
}
};
}

View File

@@ -1,31 +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 <vapours.hpp>
namespace ams::ncm {
enum class ContentType : u8 {
Meta = 0,
Program = 1,
Data = 2,
Control = 3,
HtmlDocument = 4,
LegalInformation = 5,
DeltaFragment = 6,
};
}

View File

@@ -1,32 +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 <vapours.hpp>
namespace ams::ncm {
struct DataId {
u64 value;
static const DataId Invalid;
constexpr inline auto operator<=>(const DataId &) const = default;
};
inline constexpr const DataId DataId::Invalid = {};
inline constexpr const DataId InvalidDataId = DataId::Invalid;
}

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 <vapours.hpp>
namespace ams::ncm {
struct FirmwareVariationInfo {
bool refer_to_base;
u8 _0x1[3];
u32 content_meta_count;
u8 reserved[0x18];
};
struct FirmwareVariationId {
u32 value;
};
constexpr inline bool operator==(const FirmwareVariationId &lhs, const FirmwareVariationId &rhs) {
return lhs.value == rhs.value;
}
constexpr inline bool operator!=(const FirmwareVariationId &lhs, const FirmwareVariationId &rhs) {
return lhs.value != rhs.value;
}
}

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/ncm/ncm_i_content_storage.hpp>
#include <stratosphere/ncm/ncm_i_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_memory_report.hpp>
#include <stratosphere/fs/fs_content_storage_id.hpp>
#define AMS_NCM_I_CONTENT_MANAGER_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, CreateContentStorage, (ncm::StorageId storage_id), (storage_id)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, CreateContentMetaDatabase, (ncm::StorageId storage_id), (storage_id)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, VerifyContentStorage, (ncm::StorageId storage_id), (storage_id)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, VerifyContentMetaDatabase, (ncm::StorageId storage_id), (storage_id)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, OpenContentStorage, (sf::Out<sf::SharedPointer<ncm::IContentStorage>> out, ncm::StorageId storage_id), (out, storage_id)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, OpenContentMetaDatabase, (sf::Out<sf::SharedPointer<ncm::IContentMetaDatabase>> out, ncm::StorageId storage_id), (out, storage_id)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, CloseContentStorageForcibly, (ncm::StorageId storage_id), (storage_id), hos::Version_1_0_0, hos::Version_1_0_0) \
AMS_SF_METHOD_INFO(C, H, 7, Result, CloseContentMetaDatabaseForcibly, (ncm::StorageId storage_id), (storage_id), hos::Version_1_0_0, hos::Version_1_0_0) \
AMS_SF_METHOD_INFO(C, H, 8, Result, CleanupContentMetaDatabase, (ncm::StorageId storage_id), (storage_id)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, ActivateContentStorage, (ncm::StorageId storage_id), (storage_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 10, Result, InactivateContentStorage, (ncm::StorageId storage_id), (storage_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 11, Result, ActivateContentMetaDatabase, (ncm::StorageId storage_id), (storage_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 12, Result, InactivateContentMetaDatabase, (ncm::StorageId storage_id), (storage_id), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 13, Result, InvalidateRightsIdCache, (), (), hos::Version_9_0_0) \
AMS_SF_METHOD_INFO(C, H, 14, Result, GetMemoryReport, (sf::Out<ncm::MemoryReport> out), (out), hos::Version_10_0_0) \
AMS_SF_METHOD_INFO(C, H, 15, Result, ActivateFsContentStorage, (fs::ContentStorageId fs_storage_id), (fs_storage_id)) /* Technically min 16.0.0, but used. */
AMS_SF_DEFINE_INTERFACE(ams::ncm, IContentManager, AMS_NCM_I_CONTENT_MANAGER_INTERFACE_INFO, 0xFDB4FFE1);

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/>.
*/
#pragma once
#include <stratosphere/sf.hpp>
#include <stratosphere/ncm/ncm_content_meta.hpp>
#define AMS_NCM_I_CONTENT_META_DATABASE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, Set, (const ncm::ContentMetaKey &key, const sf::InBuffer &value), (key, value)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, Get, (sf::Out<u64> out_size, const ncm::ContentMetaKey &key, const sf::OutBuffer &out_value), (out_size, key, out_value)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, Remove, (const ncm::ContentMetaKey &key), (key)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, GetContentIdByType, (sf::Out<ncm::ContentId> out_content_id, const ncm::ContentMetaKey &key, ncm::ContentType type), (out_content_id, key, type)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, ListContentInfo, (sf::Out<s32> out_entries_written, const sf::OutArray<ncm::ContentInfo> &out_info, const ncm::ContentMetaKey &key, s32 offset), (out_entries_written, out_info, key, offset)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, List, (sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ncm::ContentMetaKey> &out_info, ncm::ContentMetaType meta_type, ncm::ApplicationId application_id, u64 min, u64 max, ncm::ContentInstallType install_type), (out_entries_total, out_entries_written, out_info, meta_type, application_id, min, max, install_type)) \
AMS_SF_METHOD_INFO(C, H, 6, Result, GetLatestContentMetaKey, (sf::Out<ncm::ContentMetaKey> out_key, u64 id), (out_key, id)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, ListApplication, (sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ncm::ApplicationContentMetaKey> &out_keys, ncm::ContentMetaType meta_type), (out_entries_total, out_entries_written, out_keys, meta_type)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, Has, (sf::Out<bool> out, const ncm::ContentMetaKey &key), (out, key)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, HasAll, (sf::Out<bool> out, const sf::InArray<ncm::ContentMetaKey> &keys), (out, keys)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, GetSize, (sf::Out<u64> out_size, const ncm::ContentMetaKey &key), (out_size, key)) \
AMS_SF_METHOD_INFO(C, H, 11, Result, GetRequiredSystemVersion, (sf::Out<u32> out_version, const ncm::ContentMetaKey &key), (out_version, key)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, GetPatchContentMetaId, (sf::Out<u64> out_patch_id, const ncm::ContentMetaKey &key), (out_patch_id, key)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, DisableForcibly, (), ()) \
AMS_SF_METHOD_INFO(C, H, 14, Result, LookupOrphanContent, (const sf::OutArray<bool> &out_orphaned, const sf::InArray<ncm::ContentId> &content_ids), (out_orphaned, content_ids)) \
AMS_SF_METHOD_INFO(C, H, 15, Result, Commit, (), ()) \
AMS_SF_METHOD_INFO(C, H, 16, Result, HasContent, (sf::Out<bool> out, const ncm::ContentMetaKey &key, const ncm::ContentId &content_id), (out, key, content_id)) \
AMS_SF_METHOD_INFO(C, H, 17, Result, ListContentMetaInfo, (sf::Out<s32> out_entries_written, const sf::OutArray<ncm::ContentMetaInfo> &out_meta_info, const ncm::ContentMetaKey &key, s32 offset), (out_entries_written, out_meta_info, key, offset)) \
AMS_SF_METHOD_INFO(C, H, 18, Result, GetAttributes, (sf::Out<u8> out_attributes, const ncm::ContentMetaKey &key), (out_attributes, key)) \
AMS_SF_METHOD_INFO(C, H, 19, Result, GetRequiredApplicationVersion, (sf::Out<u32> out_version, const ncm::ContentMetaKey &key), (out_version, key), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, GetContentIdByTypeAndIdOffset, (sf::Out<ncm::ContentId> out_content_id, const ncm::ContentMetaKey &key, ncm::ContentType type, u8 id_offset), (out_content_id, key, type, id_offset), hos::Version_5_0_0) \
AMS_SF_METHOD_INFO(C, H, 21, Result, GetCount, (sf::Out<u32> out_count), (out_count), hos::Version_10_0_0) \
AMS_SF_METHOD_INFO(C, H, 22, Result, GetOwnerApplicationId, (sf::Out<ncm::ApplicationId> out_id, const ncm::ContentMetaKey &key), (out_id, key), hos::Version_10_0_0) \
AMS_SF_METHOD_INFO(C, H, 23, Result, GetContentAccessibilities, (sf::Out<u8> out_accessibilities, const ncm::ContentMetaKey &key), (out_accessibilities, key), hos::Version_15_0_0) \
AMS_SF_METHOD_INFO(C, H, 24, Result, GetContentInfoByType, (sf::Out<ncm::ContentInfo> out_content_info, const ncm::ContentMetaKey &key, ncm::ContentType type), (out_content_info, key, type), hos::Version_15_0_0) \
AMS_SF_METHOD_INFO(C, H, 25, Result, GetContentInfoByTypeAndIdOffset, (sf::Out<ncm::ContentInfo> out_content_info, const ncm::ContentMetaKey &key, ncm::ContentType type, u8 id_offset), (out_content_info, key, type, id_offset), hos::Version_15_0_0) \
AMS_SF_METHOD_INFO(C, H, 26, Result, GetPlatform, (sf::Out<ncm::ContentMetaPlatform> out, const ncm::ContentMetaKey &key), (out, key), hos::Version_17_0_0) \
AMS_SF_METHOD_INFO(C, H, 27, Result, HasAttributes, (sf::Out<u8> out, u8 attr_mask), (out, attr_mask), hos::Version_20_0_0)
AMS_SF_DEFINE_INTERFACE(ams::ncm, IContentMetaDatabase, AMS_NCM_I_CONTENT_META_DATABASE_INTERFACE_INFO, 0x58021FEC)

View File

@@ -1,64 +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/sf.hpp>
#include <stratosphere/ncm/ncm_content_id.hpp>
#include <stratosphere/ncm/ncm_placeholder_id.hpp>
#include <stratosphere/ncm/ncm_path.hpp>
#include <stratosphere/ncm/ncm_rights_id.hpp>
#define AMS_NCM_I_CONTENT_STORAGE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, GeneratePlaceHolderId, (sf::Out<ncm::PlaceHolderId> out), (out)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, CreatePlaceHolder_AtmosphereAlignmentFix, (ncm::ContentId content_id, ncm::PlaceHolderId placeholder_id, s64 size), (content_id, placeholder_id, size), hos::Version_Min, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 1, Result, CreatePlaceHolder, (ncm::PlaceHolderId placeholder_id, ncm::ContentId content_id, s64 size), (placeholder_id, content_id, size), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 2, Result, DeletePlaceHolder, (ncm::PlaceHolderId placeholder_id), (placeholder_id)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, HasPlaceHolder, (sf::Out<bool> out, ncm::PlaceHolderId placeholder_id), (out, placeholder_id)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, WritePlaceHolder, (ncm::PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data), (placeholder_id, offset, data)) \
AMS_SF_METHOD_INFO(C, H, 5, Result, Register_AtmosphereAlignmentFix, (ncm::ContentId content_id, ncm::PlaceHolderId placeholder_id), (content_id, placeholder_id), hos::Version_Min, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 5, Result, Register, (ncm::PlaceHolderId placeholder_id, ncm::ContentId content_id), (placeholder_id, content_id), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 6, Result, Delete, (ncm::ContentId content_id), (content_id)) \
AMS_SF_METHOD_INFO(C, H, 7, Result, Has, (sf::Out<bool> out, ncm::ContentId content_id), (out, content_id)) \
AMS_SF_METHOD_INFO(C, H, 8, Result, GetPath, (sf::Out<ncm::Path> out, ncm::ContentId content_id), (out, content_id)) \
AMS_SF_METHOD_INFO(C, H, 9, Result, GetPlaceHolderPath, (sf::Out<ncm::Path> out, ncm::PlaceHolderId placeholder_id), (out, placeholder_id)) \
AMS_SF_METHOD_INFO(C, H, 10, Result, CleanupAllPlaceHolder, (), ()) \
AMS_SF_METHOD_INFO(C, H, 11, Result, ListPlaceHolder, (sf::Out<s32> out_count, const sf::OutArray<ncm::PlaceHolderId> &out_buf), (out_count, out_buf)) \
AMS_SF_METHOD_INFO(C, H, 12, Result, GetContentCount, (sf::Out<s32> out_count), (out_count)) \
AMS_SF_METHOD_INFO(C, H, 13, Result, ListContentId, (sf::Out<s32> out_count, const sf::OutArray<ncm::ContentId> &out_buf, s32 start_offset), (out_count, out_buf, start_offset)) \
AMS_SF_METHOD_INFO(C, H, 14, Result, GetSizeFromContentId, (sf::Out<s64> out_size, ncm::ContentId content_id), (out_size, content_id)) \
AMS_SF_METHOD_INFO(C, H, 15, Result, DisableForcibly, (), ()) \
AMS_SF_METHOD_INFO(C, H, 16, Result, RevertToPlaceHolder_AtmosphereAlignmentFix, (ncm::ContentId old_content_id, ncm::ContentId new_content_id, ncm::PlaceHolderId placeholder_id), (old_content_id, new_content_id, placeholder_id), hos::Version_2_0_0, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 16, Result, RevertToPlaceHolder, (ncm::PlaceHolderId placeholder_id, ncm::ContentId old_content_id, ncm::ContentId new_content_id), (placeholder_id, old_content_id, new_content_id), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 17, Result, SetPlaceHolderSize, (ncm::PlaceHolderId placeholder_id, s64 size), (placeholder_id, size), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 18, Result, ReadContentIdFile, (const sf::OutBuffer &buf, ncm::ContentId content_id, s64 offset), (buf, content_id, offset), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 19, Result, GetRightsIdFromPlaceHolderIdDeprecated, (sf::Out<ams::fs::RightsId> out_rights_id, ncm::PlaceHolderId placeholder_id), (out_rights_id, placeholder_id), hos::Version_2_0_0, hos::Version_2_3_0) \
AMS_SF_METHOD_INFO(C, H, 19, Result, GetRightsIdFromPlaceHolderIdDeprecated2, (sf::Out<ncm::RightsId> out_rights_id, ncm::PlaceHolderId placeholder_id), (out_rights_id, placeholder_id), hos::Version_3_0_0, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 19, Result, GetRightsIdFromPlaceHolderId, (sf::Out<ncm::RightsId> out_rights_id, ncm::PlaceHolderId placeholder_id, fs::ContentAttributes attr), (out_rights_id, placeholder_id, attr), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, GetRightsIdFromContentIdDeprecated, (sf::Out<ams::fs::RightsId> out_rights_id, ncm::ContentId content_id), (out_rights_id, content_id), hos::Version_2_0_0, hos::Version_2_3_0) \
AMS_SF_METHOD_INFO(C, H, 20, Result, GetRightsIdFromContentIdDeprecated2, (sf::Out<ncm::RightsId> out_rights_id, ncm::ContentId content_id), (out_rights_id, content_id), hos::Version_3_0_0, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 20, Result, GetRightsIdFromContentId, (sf::Out<ncm::RightsId> out_rights_id, ncm::ContentId content_id, fs::ContentAttributes attr), (out_rights_id, content_id, attr), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 21, Result, WriteContentForDebug, (ncm::ContentId content_id, s64 offset, const sf::InBuffer &data), (content_id, offset, data), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 22, Result, GetFreeSpaceSize, (sf::Out<s64> out_size), (out_size), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 23, Result, GetTotalSpaceSize, (sf::Out<s64> out_size), (out_size), hos::Version_2_0_0) \
AMS_SF_METHOD_INFO(C, H, 24, Result, FlushPlaceHolder, (), (), hos::Version_3_0_0) \
AMS_SF_METHOD_INFO(C, H, 25, Result, GetSizeFromPlaceHolderId, (sf::Out<s64> out, ncm::PlaceHolderId placeholder_id), (out, placeholder_id), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 26, Result, RepairInvalidFileAttribute, (), (), hos::Version_4_0_0) \
AMS_SF_METHOD_INFO(C, H, 27, Result, GetRightsIdFromPlaceHolderIdWithCacheDeprecated, (sf::Out<ncm::RightsId> out_rights_id, ncm::ContentId cache_content_id, ncm::PlaceHolderId placeholder_id), (out_rights_id, cache_content_id, placeholder_id), hos::Version_8_0_0, hos::Version_15_0_1) \
AMS_SF_METHOD_INFO(C, H, 27, Result, GetRightsIdFromPlaceHolderIdWithCache, (sf::Out<ncm::RightsId> out_rights_id, ncm::PlaceHolderId placeholder_id, ncm::ContentId cache_content_id, fs::ContentAttributes attr), (out_rights_id, placeholder_id, cache_content_id, attr), hos::Version_16_0_0) \
AMS_SF_METHOD_INFO(C, H, 28, Result, RegisterPath, (const ncm::ContentId &content_id, const ncm::Path &path), (content_id, path), hos::Version_13_0_0) \
AMS_SF_METHOD_INFO(C, H, 29, Result, ClearRegisteredPath, (), (), hos::Version_13_0_0) \
AMS_SF_METHOD_INFO(C, H, 30, Result, GetProgramId, (sf::Out<ncm::ProgramId> out, ncm::ContentId content_id, fs::ContentAttributes attr), (out, content_id, attr), hos::Version_17_0_0)
AMS_SF_DEFINE_INTERFACE(ams::ncm, IContentStorage, AMS_NCM_I_CONTENT_STORAGE_INTERFACE_INFO, 0xFEAE3DD1)

View File

@@ -1,20 +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/ncm/ncm_data_id.hpp>
#include <stratosphere/ncm/ncm_program_id.hpp>
#include <stratosphere/ncm/ncm_content_meta_id.hpp>
#include <stratosphere/ncm/ncm_system_content_meta_id.hpp>

View File

@@ -1,45 +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
namespace ams::ncm {
enum class InstallProgressState : u8 {
NotPrepared = 0,
DataPrepared = 1,
Prepared = 2,
Downloaded = 3,
Committed = 4,
Fatal = 5,
};
struct InstallProgress {
InstallProgressState state;
u8 pad[3];
util::TypedStorage<Result> last_result;
s64 installed_size;
s64 total_size;
Result GetLastResult() const {
return util::GetReference(last_result);
}
void SetLastResult(Result result) {
*util::GetPointer(last_result) = result;
}
};
}

View File

@@ -1,203 +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/ncm/ncm_install_task_data.hpp>
#include <stratosphere/ncm/ncm_install_task_occupied_size.hpp>
namespace ams::ncm {
enum class ListContentMetaKeyFilter : u8 {
All = 0,
Committed = 1,
NotCommitted = 2,
};
enum InstallConfig {
InstallConfig_None = (0 << 0),
InstallConfig_SystemUpdate = (1 << 2),
InstallConfig_RequiresExFatDriver = (1 << 3),
InstallConfig_IgnoreTicket = (1 << 4),
};
struct InstallThroughput {
s64 installed;
TimeSpan elapsed_time;
};
struct InstallContentMetaInfo {
ContentId content_id;
s64 content_size;
ContentMetaKey key;
bool verify_digest;
bool has_key;
Digest digest;
static constexpr InstallContentMetaInfo MakeVerifiable(const ContentId &cid, s64 sz, const ContentMetaKey &ky, const Digest &d) {
return {
.content_id = cid,
.content_size = sz,
.key = ky,
.verify_digest = true,
.has_key = true,
.digest = d,
};
}
static constexpr InstallContentMetaInfo MakeUnverifiable(const ContentId &cid, s64 sz, const ContentMetaKey &ky) {
return {
.content_id = cid,
.content_size = sz,
.key = ky,
.verify_digest = false,
.has_key = true,
};
}
static constexpr InstallContentMetaInfo MakeUnverifiable(const ContentId &cid, s64 sz) {
return {
.content_id = cid,
.content_size = sz,
.verify_digest = false,
.has_key = false,
};
}
};
static_assert(sizeof(InstallContentMetaInfo) == 0x50);
class InstallTaskBase {
NON_COPYABLE(InstallTaskBase);
NON_MOVEABLE(InstallTaskBase);
private:
crypto::Sha256Generator m_sha256_generator{};
StorageId m_install_storage{};
InstallTaskDataBase *m_data{};
InstallProgress m_progress{};
os::SdkMutex m_progress_mutex{};
u32 m_config{};
os::SdkMutex m_cancel_mutex{};
bool m_cancel_requested{};
InstallThroughput m_throughput{};
TimeSpan m_throughput_start_time{};
os::SdkMutex m_throughput_mutex{};
FirmwareVariationId m_firmware_variation_id{};
private:
ALWAYS_INLINE Result SetLastResultOnFailure(Result result) {
if (R_FAILED(result)) {
this->SetLastResult(result);
}
R_RETURN(result);
}
public:
InstallTaskBase() : m_data(), m_progress(), m_progress_mutex(), m_cancel_mutex(), m_cancel_requested(), m_throughput_mutex() { /* ... */ }
virtual ~InstallTaskBase() { /* ... */ };
public:
virtual void Cancel();
virtual void ResetCancel();
Result Prepare();
Result GetPreparedPlaceHolderPath(Path *out_path, u64 id, ContentMetaType meta_type, ContentType type);
Result CalculateRequiredSize(s64 *out_size);
Result Cleanup();
Result ListContentMetaKey(s32 *out_keys_written, StorageContentMetaKey *out_keys, s32 out_keys_count, s32 offset, ListContentMetaKeyFilter filter);
Result ListContentMetaKey(s32 *out_keys_written, StorageContentMetaKey *out_keys, s32 out_keys_count, s32 offset) { R_RETURN(this->ListContentMetaKey(out_keys_written, out_keys, out_keys_count, offset, ListContentMetaKeyFilter::All)); }
Result ListApplicationContentMetaKey(s32 *out_keys_written, ApplicationContentMetaKey *out_keys, s32 out_keys_count, s32 offset);
Result Execute();
Result PrepareAndExecute();
Result Commit(const StorageContentMetaKey *keys, s32 num_keys);
Result Commit() { R_RETURN(this->Commit(nullptr, 0)); }
virtual InstallProgress GetProgress();
void ResetLastResult();
Result IncludesExFatDriver(bool *out);
InstallThroughput GetThroughput();
Result CalculateContentsSize(s64 *out_size, const ContentMetaKey &key, StorageId storage_id);
Result ListOccupiedSize(s32 *out_written, InstallTaskOccupiedSize *out_list, s32 out_list_size, s32 offset);
Result FindMaxRequiredApplicationVersion(u32 *out);
Result FindMaxRequiredSystemVersion(u32 *out);
protected:
Result Initialize(StorageId install_storage, InstallTaskDataBase *data, u32 config);
Result PrepareContentMeta(const InstallContentMetaInfo &meta_info, util::optional<ContentMetaKey> key, util::optional<u32> source_version);
Result PrepareContentMeta(ContentId content_id, s64 size, ContentMetaType meta_type, AutoBuffer *buffer);
Result WritePlaceHolderBuffer(InstallContentInfo *content_info, const void *data, size_t data_size);
void PrepareAgain();
Result CountInstallContentMetaData(s32 *out_count);
Result GetInstallContentMetaData(InstallContentMeta *out_content_meta, s32 index);
Result DeleteInstallContentMetaData(const ContentMetaKey *keys, s32 num_keys);
virtual Result GetInstallContentMetaInfo(InstallContentMetaInfo *out_info, const ContentMetaKey &key) = 0;
virtual Result PrepareDependency();
Result PrepareSystemUpdateDependency();
virtual Result PrepareContentMetaIfLatest(const ContentMetaKey &key); /* NOTE: This is not virtual in Nintendo's code. We do so to facilitate downgrades. */
u32 GetConfig() const { return m_config; }
Result WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, util::optional<bool> is_temporary);
StorageId GetInstallStorage() const { return m_install_storage; }
virtual Result OnPrepareComplete() { R_SUCCEED(); }
Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out);
Result CanContinue();
private:
bool IsCancelRequested();
Result PrepareImpl();
Result ExecuteImpl();
Result CommitImpl(const StorageContentMetaKey *keys, s32 num_keys);
Result CleanupOne(const InstallContentMeta &content_meta);
Result VerifyAllNotCommitted(const StorageContentMetaKey *keys, s32 num_keys);
virtual Result PrepareInstallContentMetaData() = 0;
virtual Result GetLatestVersion(util::optional<u32> *out_version, u64 id) { AMS_UNUSED(out_version, id); R_THROW(ncm::ResultContentMetaNotFound()); }
virtual Result OnExecuteComplete() { R_SUCCEED(); }
Result WritePlaceHolder(const ContentMetaKey &key, InstallContentInfo *content_info);
virtual Result OnWritePlaceHolder(const ContentMetaKey &key, InstallContentInfo *content_info) = 0;
bool IsNecessaryInstallTicket(const fs::RightsId &rights_id);
virtual Result InstallTicket(const fs::RightsId &rights_id, ContentMetaType meta_type) = 0;
Result IsNewerThanInstalled(bool *out, const ContentMetaKey &key);
Result PreparePlaceHolder();
void SetProgressState(InstallProgressState state);
void IncrementProgress(s64 size);
void SetTotalSize(s64 size);
void SetLastResult(Result last_result);
void CleanupProgress();
void ResetThroughputMeasurement();
void StartThroughputMeasurement();
void UpdateThroughputMeasurement(s64 throughput);
Result GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, util::optional<u32> source_version);
InstallContentInfo MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, util::optional<bool> is_temporary);
Result ReadContentMetaInfoList(s32 *out_count, std::unique_ptr<ContentMetaInfo[]> *out_meta_infos, const ContentMetaKey &key, fs::ContentAttributes attr);
Result ListRightsIdsByInstallContentMeta(s32 *out_count, Span<RightsId> out_span, const InstallContentMeta &content_meta, s32 offset);
public:
virtual Result CheckInstallable() { R_SUCCEED(); }
void SetFirmwareVariationId(FirmwareVariationId id) { m_firmware_variation_id = id; }
Result ListRightsIds(s32 *out_count, Span<RightsId> out_span, const ContentMetaKey &key, s32 offset);
};
}

View File

@@ -1,149 +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/ncm/ncm_content_meta.hpp>
#include <stratosphere/ncm/ncm_install_progress.hpp>
#include <stratosphere/ncm/ncm_system_update_task_apply_info.hpp>
namespace ams::ncm {
struct InstallContentMeta {
std::unique_ptr<char[]> data;
size_t size;
InstallContentMetaReader GetReader() const {
return InstallContentMetaReader(this->data.get(), this->size);
}
InstallContentMetaWriter GetWriter() const {
return InstallContentMetaWriter(this->data.get(), this->size);
}
};
class InstallTaskDataBase {
public:
Result Get(InstallContentMeta *out, s32 index);
Result Update(const InstallContentMeta &content_meta, s32 index);
Result Has(bool *out, u64 id);
public:
virtual Result GetProgress(InstallProgress *out_progress) = 0;
virtual Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out_info) = 0;
virtual Result SetState(InstallProgressState state) = 0;
virtual Result SetLastResult(Result result) = 0;
virtual Result SetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo info) = 0;
virtual Result Push(const void *data, size_t data_size) = 0;
virtual Result Count(s32 *out) = 0;
virtual Result Delete(const ContentMetaKey *keys, s32 num_keys) = 0;
virtual Result Cleanup() = 0;
private:
virtual Result GetSize(size_t *out_size, s32 index) = 0;
virtual Result Get(s32 index, void *out, size_t out_size) = 0;
virtual Result Update(s32 index, const void *data, size_t data_size) = 0;
};
class MemoryInstallTaskData : public InstallTaskDataBase {
private:
struct DataHolder : public InstallContentMeta, public util::IntrusiveListBaseNode<DataHolder>{};
using DataList = util::IntrusiveListBaseTraits<DataHolder>::ListType;
private:
DataList m_data_list;
InstallProgressState m_state;
Result m_last_result;
SystemUpdateTaskApplyInfo m_system_update_task_apply_info;
public:
MemoryInstallTaskData() : m_data_list(), m_state(InstallProgressState::NotPrepared), m_last_result(ResultSuccess()), m_system_update_task_apply_info() { /* ... */ };
~MemoryInstallTaskData() {
this->Cleanup();
}
public:
virtual Result GetProgress(InstallProgress *out_progress) override;
virtual Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out_info) override;
virtual Result SetState(InstallProgressState state) override;
virtual Result SetLastResult(Result result) override;
virtual Result SetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo info) override;
virtual Result Push(const void *data, size_t data_size) override;
virtual Result Count(s32 *out) override;
virtual Result Delete(const ContentMetaKey *keys, s32 num_keys) override;
virtual Result Cleanup() override;
private:
virtual Result GetSize(size_t *out_size, s32 index) override;
virtual Result Get(s32 index, void *out, size_t out_size) override;
virtual Result Update(s32 index, const void *data, size_t data_size) override;
};
class FileInstallTaskData : public InstallTaskDataBase {
private:
struct Header {
u32 max_entries;
u32 count;
s64 last_data_offset;
Result last_result;
InstallProgressState progress_state;
SystemUpdateTaskApplyInfo system_update_task_apply_info;
};
static_assert(sizeof(Header) == 0x18);
struct EntryInfo {
s64 offset;
s64 size;
};
static_assert(sizeof(EntryInfo) == 0x10);
private:
Header m_header{};
char m_path[64]{};
private:
static constexpr Header MakeInitialHeader(s32 max_entries) {
return {
.max_entries = static_cast<u32>(max_entries),
.count = 0,
.last_data_offset = GetEntryInfoOffset(max_entries),
.last_result = ResultSuccess(),
.progress_state = InstallProgressState::NotPrepared,
.system_update_task_apply_info = SystemUpdateTaskApplyInfo::Unknown,
};
}
static constexpr s64 GetEntryInfoOffset(s32 index) {
return index * sizeof(EntryInfo) + sizeof(Header);
}
public:
static Result Create(const char *path, s32 max_entries);
Result Initialize(const char *path);
public:
virtual Result GetProgress(InstallProgress *out_progress) override;
virtual Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out_info) override;
virtual Result SetState(InstallProgressState state) override;
virtual Result SetLastResult(Result result) override;
virtual Result SetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo info) override;
virtual Result Push(const void *data, size_t data_size) override;
virtual Result Count(s32 *out) override;
virtual Result Delete(const ContentMetaKey *keys, s32 num_keys) override;
virtual Result Cleanup() override;
private:
virtual Result GetSize(size_t *out_size, s32 index) override;
virtual Result Get(s32 index, void *out, size_t out_size) override;
virtual Result Update(s32 index, const void *data, size_t data_size) override;
Result GetEntryInfo(EntryInfo *out_entry_info, s32 index);
Result Write(const void *data, size_t size, s64 offset);
Result Read(void *out, size_t out_size, s64 offset);
Result WriteHeader();
};
}

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/>.
*/
#pragma once
#include <stratosphere/ncm/ncm_content_meta_key.hpp>
namespace ams::ncm {
struct InstallTaskOccupiedSize {
ContentMetaKey key;
s64 size;
StorageId storage_id;
u8 reserved[7];
};
static_assert(sizeof(InstallTaskOccupiedSize) == 0x20);
}

View File

@@ -1,79 +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 <stratosphere/ncm/ncm_i_content_meta_database.hpp>
#include <stratosphere/ncm/ncm_integrated_list.hpp>
namespace ams::ncm {
class IntegratedContentMetaDatabaseImpl {
NON_COPYABLE(IntegratedContentMetaDatabaseImpl);
NON_MOVEABLE(IntegratedContentMetaDatabaseImpl);
private:
using ListType = ncm::IntegratedList<ncm::IContentMetaDatabase, 2>;
using DataType = ListType::ListData;
private:
os::SdkRecursiveMutex m_mutex;
ListType m_list;
bool m_disabled;
public:
IntegratedContentMetaDatabaseImpl() : m_mutex(), m_list(), m_disabled(false) { /* ... */ }
void Add(sf::SharedPointer<ncm::IContentMetaDatabase> p, u8 id) {
DataType data = {std::move(p), id};
m_list.Add(data);
}
private:
/* Helpers. */
Result EnsureEnabled() const {
R_UNLESS(!m_disabled, ncm::ResultInvalidContentMetaDatabase());
R_SUCCEED();
}
public:
/* Actual commands. */
Result Set(const ContentMetaKey &key, const sf::InBuffer &value);
Result Get(sf::Out<u64> out_size, const ContentMetaKey &key, const sf::OutBuffer &out_value);
Result Remove(const ContentMetaKey &key);
Result GetContentIdByType(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type);
Result ListContentInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentInfo> &out_info, const ContentMetaKey &key, s32 offset);
Result List(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaKey> &out_info, ContentMetaType meta_type, ApplicationId application_id, u64 min, u64 max, ContentInstallType install_type);
Result GetLatestContentMetaKey(sf::Out<ContentMetaKey> out_key, u64 id);
Result ListApplication(sf::Out<s32> out_entries_total, sf::Out<s32> out_entries_written, const sf::OutArray<ApplicationContentMetaKey> &out_keys, ContentMetaType meta_type);
Result Has(sf::Out<bool> out, const ContentMetaKey &key);
Result HasAll(sf::Out<bool> out, const sf::InArray<ContentMetaKey> &keys);
Result GetSize(sf::Out<u64> out_size, const ContentMetaKey &key);
Result GetRequiredSystemVersion(sf::Out<u32> out_version, const ContentMetaKey &key);
Result GetPatchContentMetaId(sf::Out<u64> out_patch_id, const ContentMetaKey &key);
Result DisableForcibly();
Result LookupOrphanContent(const sf::OutArray<bool> &out_orphaned, const sf::InArray<ContentId> &content_ids);
Result Commit();
Result HasContent(sf::Out<bool> out, const ContentMetaKey &key, const ContentId &content_id);
Result ListContentMetaInfo(sf::Out<s32> out_entries_written, const sf::OutArray<ContentMetaInfo> &out_meta_info, const ContentMetaKey &key, s32 offset);
Result GetAttributes(sf::Out<u8> out_attributes, const ContentMetaKey &key);
Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key);
Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset);
Result GetCount(sf::Out<u32> out_count);
Result GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key);
Result GetContentAccessibilities(sf::Out<u8> out_accessibilities, const ContentMetaKey &key);
Result GetContentInfoByType(sf::Out<ContentInfo> out_content_info, const ContentMetaKey &key, ContentType type);
Result GetContentInfoByTypeAndIdOffset(sf::Out<ContentInfo> out_content_info, const ContentMetaKey &key, ContentType type, u8 id_offset);
Result GetPlatform(sf::Out<ncm::ContentMetaPlatform> out, const ContentMetaKey &key);
Result HasAttributes(sf::Out<u8> out, u8 attr_mask);
};
static_assert(ncm::IsIContentMetaDatabase<IntegratedContentMetaDatabaseImpl>);
}

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/>.
*/
#pragma once
#include <stratosphere.hpp>
#include <stratosphere/ncm/ncm_i_content_storage.hpp>
#include <stratosphere/ncm/ncm_integrated_list.hpp>
namespace ams::ncm {
class IntegratedContentStorageImpl {
NON_COPYABLE(IntegratedContentStorageImpl);
NON_MOVEABLE(IntegratedContentStorageImpl);
private:
using ListType = ncm::IntegratedList<ncm::IContentStorage, 2>;
using DataType = ListType::ListData;
private:
os::SdkRecursiveMutex m_mutex;
ListType m_list;
bool m_disabled;
public:
IntegratedContentStorageImpl() : m_mutex(), m_list(), m_disabled(false) { /* ... */ }
void Add(sf::SharedPointer<ncm::IContentStorage> p, u8 id) {
DataType data = {std::move(p), id};
m_list.Add(data);
}
private:
/* Helpers. */
Result EnsureEnabled() const {
R_UNLESS(!m_disabled, ncm::ResultInvalidContentStorage());
R_SUCCEED();
}
public:
/* Actual commands. */
Result GeneratePlaceHolderId(sf::Out<PlaceHolderId> out);
Result CreatePlaceHolder(PlaceHolderId placeholder_id, ContentId content_id, s64 size);
Result DeletePlaceHolder(PlaceHolderId placeholder_id);
Result HasPlaceHolder(sf::Out<bool> out, PlaceHolderId placeholder_id);
Result WritePlaceHolder(PlaceHolderId placeholder_id, s64 offset, const sf::InBuffer &data);
Result Register(PlaceHolderId placeholder_id, ContentId content_id);
Result Delete(ContentId content_id);
Result Has(sf::Out<bool> out, ContentId content_id);
Result GetPath(sf::Out<Path> out, ContentId content_id);
Result GetPlaceHolderPath(sf::Out<Path> out, PlaceHolderId placeholder_id);
Result CleanupAllPlaceHolder();
Result ListPlaceHolder(sf::Out<s32> out_count, const sf::OutArray<PlaceHolderId> &out_buf);
Result GetContentCount(sf::Out<s32> out_count);
Result ListContentId(sf::Out<s32> out_count, const sf::OutArray<ContentId> &out_buf, s32 start_offset);
Result GetSizeFromContentId(sf::Out<s64> out_size, ContentId content_id);
Result DisableForcibly();
Result RevertToPlaceHolder(PlaceHolderId placeholder_id, ContentId old_content_id, ContentId new_content_id);
Result SetPlaceHolderSize(PlaceHolderId placeholder_id, s64 size);
Result ReadContentIdFile(const sf::OutBuffer &buf, ContentId content_id, s64 offset);
Result GetRightsIdFromPlaceHolderIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, PlaceHolderId placeholder_id);
Result GetRightsIdFromPlaceHolderIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id);
Result GetRightsIdFromPlaceHolderId(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, fs::ContentAttributes attr);
Result GetRightsIdFromContentIdDeprecated(sf::Out<ams::fs::RightsId> out_rights_id, ContentId content_id);
Result GetRightsIdFromContentIdDeprecated2(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id);
Result GetRightsIdFromContentId(sf::Out<ncm::RightsId> out_rights_id, ContentId content_id, fs::ContentAttributes attr);
Result WriteContentForDebug(ContentId content_id, s64 offset, const sf::InBuffer &data);
Result GetFreeSpaceSize(sf::Out<s64> out_size);
Result GetTotalSpaceSize(sf::Out<s64> out_size);
Result FlushPlaceHolder();
Result GetSizeFromPlaceHolderId(sf::Out<s64> out, PlaceHolderId placeholder_id);
Result RepairInvalidFileAttribute();
Result GetRightsIdFromPlaceHolderIdWithCache(sf::Out<ncm::RightsId> out_rights_id, PlaceHolderId placeholder_id, ContentId cache_content_id, fs::ContentAttributes attr);
Result RegisterPath(const ContentId &content_id, const Path &path);
Result ClearRegisteredPath();
Result GetProgramId(sf::Out<ncm::ProgramId> out, ContentId content_id, fs::ContentAttributes attr);
/* 16.0.0 Alignment change hacks. */
Result CreatePlaceHolder_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id, s64 size) { R_RETURN(this->CreatePlaceHolder(placeholder_id, content_id, size)); }
Result Register_AtmosphereAlignmentFix(ContentId content_id, PlaceHolderId placeholder_id) { R_RETURN(this->Register(placeholder_id, content_id)); }
Result RevertToPlaceHolder_AtmosphereAlignmentFix(ncm::ContentId old_content_id, ncm::ContentId new_content_id, ncm::PlaceHolderId placeholder_id) { R_RETURN(this->RevertToPlaceHolder(placeholder_id, old_content_id, new_content_id)); }
Result GetRightsIdFromPlaceHolderIdWithCacheDeprecated(sf::Out<ncm::RightsId> out_rights_id, ContentId cache_content_id, PlaceHolderId placeholder_id) { R_RETURN(this->GetRightsIdFromPlaceHolderIdWithCache(out_rights_id, placeholder_id, cache_content_id, fs::ContentAttributes_None)); }
};
static_assert(ncm::IsIContentStorage<IntegratedContentStorageImpl>);
}

View File

@@ -1,91 +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 <vapours.hpp>
#include <stratosphere/sf/sf_shared_object.hpp>
namespace ams::ncm {
template<typename T, size_t N>
class IntegratedList {
static_assert(N <= std::numeric_limits<u8>::max());
public:
struct ListData {
sf::SharedPointer<T> interface;
u8 id;
};
private:
size_t m_count;
sf::SharedPointer<T> m_interfaces[N];
u8 m_ids[N];
public:
IntegratedList() : m_count(0), m_interfaces(), m_ids() { /* ... */ }
void Add(ListData &data) {
/* Find place to insert into the list. */
const size_t pos = std::distance(std::begin(m_ids), std::lower_bound(std::begin(m_ids), std::end(m_ids), data.id));
/* If we need to, move stuff to make space. */
if (m_ids[pos] > data.id) {
AMS_ABORT_UNLESS(m_count < N);
for (size_t i = m_count; i > pos; --i) {
m_ids[i] = std::move(m_ids[i - 1]);
m_interfaces[i] = std::move(m_interfaces[i - 1]);
}
/* If we're inserting somewhere in the middle, increment count. */
m_count++;
} else if (m_ids[pos] < data.id) {
/* If we're inserting at the end, increment count. */
AMS_ABORT_UNLESS(m_count < N);
m_count++;
}
/* Set at position. */
m_interfaces[pos] = data.interface;
m_ids[pos] = data.id;
}
ListData Get(size_t idx) {
AMS_ABORT_UNLESS(idx < m_count);
return { m_interfaces[idx], m_ids[idx] };
}
Result TryEach(auto callback) {
Result result = ResultSuccess();
for (size_t i = 0; i < m_count; ++i) {
result = callback(this->Get(i));
if (R_SUCCEEDED(result)) {
break;
}
}
R_RETURN(result);
}
Result ForAll(auto callback) {
for (size_t i = 0; i < m_count; ++i) {
R_TRY(callback(this->Get(i)));
}
R_SUCCEED();
}
size_t GetCount() const { return m_count; }
};
}

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/ncm/ncm_content_id.hpp>
#include <stratosphere/ncm/ncm_placeholder_id.hpp>
#include <stratosphere/ncm/ncm_path_string.hpp>
namespace ams::ncm {
using MakeContentPathFunction = void (*)(PathString *out, ContentId content_id, const char *root_path);
using MakePlaceHolderPathFunction = void (*)(PathString *out, PlaceHolderId placeholder_id,const char *root_path);
void MakeFlatContentFilePath(PathString *out, ContentId content_id, const char *root_path);
void MakeSha256HierarchicalContentFilePath_ForFat4KCluster(PathString *out, ContentId content_id, const char *root_path);
void MakeSha256HierarchicalContentFilePath_ForFat16KCluster(PathString *out, ContentId content_id, const char *root_path);
void MakeSha256HierarchicalContentFilePath_ForFat32KCluster(PathString *out, ContentId content_id, const char *root_path);
size_t GetHierarchicalContentDirectoryDepth(MakeContentPathFunction func);
void MakeFlatPlaceHolderFilePath(PathString *out, PlaceHolderId placeholder_id, const char *root_path);
void MakeSha256HierarchicalPlaceHolderFilePath_ForFat16KCluster(PathString *out, PlaceHolderId placeholder_id, const char *root_pathroot);
size_t GetHierarchicalPlaceHolderDirectoryDepth(MakePlaceHolderPathFunction func);
}

View File

@@ -1,55 +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::ncm {
struct MappedMemory {
u64 id;
size_t offset;
u8 *buffer;
size_t buffer_size;
bool IsIncluded(size_t o, size_t sz) const {
return this->offset <= o && sz <= this->buffer_size && (o + sz) <= (this->offset + this->buffer_size);
}
u8 *GetBuffer(size_t o, size_t sz) const {
AMS_ASSERT(this->buffer != nullptr);
AMS_ASSERT(this->IsIncluded(o, sz));
AMS_UNUSED(sz);
return this->buffer + (o - this->offset);
}
};
static_assert(util::is_pod<MappedMemory>::value);
class IMapper {
public:
virtual ~IMapper() { /* ... */ }
public:
virtual Result GetMappedMemory(MappedMemory *out, size_t offset, size_t size) = 0;
virtual Result MarkUsing(u64 id) = 0;
virtual Result UnmarkUsing(u64 id) = 0;
virtual Result MarkDirty(u64 id) = 0;
protected:
virtual Result MapImpl(MappedMemory *out, Span<u8> data, size_t offset, size_t size) = 0;
virtual Result UnmapImpl(MappedMemory *mem) = 0;
virtual bool IsAccessibleSizeUpdatable() = 0;
};
}

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 <vapours.hpp>
namespace ams::ncm {
constexpr inline s32 SystemMaxContentMetaCount = 0x800;
constexpr inline s32 GameCardMaxContentMetaCount = 0x800;
constexpr inline s32 HostMaxContentMetaCount = 0x800;
constexpr inline s32 UserMaxContentMetaCount = 0x2000;
constexpr inline s32 SdCardMaxContentMetaCount = 0x2000;
}

View File

@@ -1,59 +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 <vapours.hpp>
#include <stratosphere/os.hpp>
#include <stratosphere/lmem/lmem_common.hpp>
namespace ams::ncm {
struct MemoryResourceState {
size_t peak_total_alloc_size;
size_t peak_alloc_size;
size_t allocatable_size;
size_t total_free_size;
};
static_assert(sizeof(MemoryResourceState) == 0x20);
struct MemoryReport {
MemoryResourceState system_content_meta_resource_state;
MemoryResourceState sd_and_user_content_meta_resource_state;
MemoryResourceState gamecard_content_meta_resource_state;
MemoryResourceState heap_resource_state;
};
static_assert(sizeof(MemoryReport) == 0x80);
class HeapState {
private:
os::SdkMutex m_mutex;
lmem::HeapHandle m_heap_handle;
size_t m_total_alloc_size;
size_t m_peak_total_alloc_size;
size_t m_peak_alloc_size;
public:
constexpr HeapState() : m_mutex(), m_heap_handle(nullptr), m_total_alloc_size(0), m_peak_total_alloc_size(0), m_peak_alloc_size(0) { /* ... */ }
void Initialize(lmem::HeapHandle heap_handle);
void Allocate(size_t size);
void Free(size_t size);
void GetMemoryResourceState(MemoryResourceState *out);
};
HeapState &GetHeapState();
}

View File

@@ -1,33 +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/ncm/ncm_package_install_task_base.hpp>
namespace ams::ncm {
class PackageInstallTask : public PackageInstallTaskBase {
private:
MemoryInstallTaskData m_data{};
public:
Result Initialize(const char *package_root, StorageId storage_id, void *buffer, size_t buffer_size, bool ignore_ticket);
protected:
bool IsContentMetaContentName(const char *name);
virtual Result PrepareInstallContentMetaData() override;
private:
virtual Result GetInstallContentMetaInfo(InstallContentMetaInfo *out_info, const ContentMetaKey &key) override;
};
}

View File

@@ -1,47 +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/kvdb/kvdb_bounded_string.hpp>
#include <stratosphere/ncm/ncm_install_task_base.hpp>
namespace ams::ncm {
class PackageInstallTaskBase : public InstallTaskBase {
private:
using PackagePath = kvdb::BoundedString<256>;
private:
PackagePath m_package_root;
void *m_buffer{};
size_t m_buffer_size{};
public:
PackageInstallTaskBase() : m_package_root() { /* ... */ }
Result Initialize(const char *package_root_path, void *buffer, size_t buffer_size, StorageId storage_id, InstallTaskDataBase *data, u32 config);
protected:
const char *GetPackageRootPath() {
return m_package_root.Get();
}
private:
virtual Result OnWritePlaceHolder(const ContentMetaKey &key, InstallContentInfo *content_info) override;
virtual Result InstallTicket(const fs::RightsId &rights_id, ContentMetaType meta_type) override;
void CreateContentMetaPath(PackagePath *out_path, ContentId content_id);
void CreateContentPath(PackagePath *out_path, ContentId content_id);
void CreateTicketPath(PackagePath *out_path, fs::RightsId id);
void CreateCertificatePath(PackagePath *out_path, fs::RightsId id);
};
}

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/>.
*/
#pragma once
#include <stratosphere/ncm/ncm_package_system_update_task.hpp>
namespace ams::ncm {
class PackageSystemDowngradeTask : public PackageSystemUpdateTask {
public:
Result Commit();
protected:
virtual Result PrepareContentMetaIfLatest(const ContentMetaKey &key) override;
private:
Result PreCommit();
};
}

View File

@@ -1,45 +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/ncm/ncm_package_install_task_base.hpp>
namespace ams::ncm {
class PackageSystemUpdateTask : public PackageInstallTaskBase {
private:
using PackagePath = kvdb::BoundedString<0x100>;
private:
PackagePath m_context_path{};
FileInstallTaskData m_data{};
ContentMetaDatabase m_package_db{};
bool m_gamecard_content_meta_database_active{};
public:
~PackageSystemUpdateTask();
void Inactivate();
Result Initialize(const char *package_root, const char *context_path, void *buffer, size_t buffer_size, bool requires_exfat_driver, FirmwareVariationId firmware_variation_id);
util::optional<ContentMetaKey> GetSystemUpdateMetaKey();
protected:
virtual Result PrepareInstallContentMetaData() override;
virtual Result GetInstallContentMetaInfo(InstallContentMetaInfo *out, const ContentMetaKey &key) override;
InstallTaskDataBase &GetInstallData() { return m_data; } /* Atmosphere extension. */
private:
virtual Result PrepareDependency() override;
Result GetContentInfoOfContentMeta(ContentInfo *out, const ContentMetaKey &key);
};
}

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/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/fs/fs_directory.hpp>
#include <stratosphere/sf/sf_buffer_tags.hpp>
namespace ams::ncm {
struct alignas(4) Path : ams::sf::LargeData {
char str[fs::EntryNameLengthMax];
static constexpr Path Encode(const char *p) {
Path path = {};
/* Copy C string to path, terminating when a null byte is found. */
for (size_t i = 0; i < sizeof(path) - 1; i++) {
path.str[i] = p[i];
if (p[i] == '\x00') {
break;
}
}
return 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/fs/fs_directory.hpp>
#include <stratosphere/kvdb/kvdb_bounded_string.hpp>
namespace ams::ncm {
using PathString = kvdb::BoundedString<fs::EntryNameLengthMax>;
}

View File

@@ -1,45 +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 <vapours.hpp>
namespace ams::ncm {
struct PlaceHolderId {
util::Uuid uuid;
bool operator==(const PlaceHolderId &other) const {
return this->uuid == other.uuid;
}
bool operator!=(const PlaceHolderId &other) const {
return this->uuid != other.uuid;
}
bool operator==(const util::Uuid &other) const {
return this->uuid == other;
}
bool operator!=(const util::Uuid &other) const {
return this->uuid != other;
}
};
static_assert(alignof(PlaceHolderId) == 1);
constexpr inline PlaceHolderId InvalidPlaceHolderId = { util::InvalidUuid };
}

View File

@@ -1,36 +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 <vapours.hpp>
namespace ams::ncm {
struct ProgramId {
u64 value;
#if defined(ATMOSPHERE_OS_HORIZON)
inline explicit operator svc::ProgramId() const {
static_assert(sizeof(value) == sizeof(svc::ProgramId));
return { this->value };
}
#endif
constexpr inline auto operator<=>(const ProgramId &) const = default;
};
inline constexpr const ProgramId InvalidProgramId = {};
}

View File

@@ -1,36 +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/ncm/ncm_program_id.hpp>
#include <stratosphere/ncm/ncm_storage_id.hpp>
namespace ams::ncm {
struct ProgramLocation {
ProgramId program_id;
u8 storage_id;
static constexpr ProgramLocation Make(ProgramId program_id, StorageId storage_id) {
return { .program_id = program_id, .storage_id = static_cast<u8>(storage_id), };
}
};
static_assert(sizeof(ProgramLocation) == 0x10 && util::is_pod<ProgramLocation>::value);
#if defined(ATMOSPHERE_OS_HORIZON)
static_assert(sizeof(ProgramLocation) == sizeof(::NcmProgramLocation) && alignof(ProgramLocation) == alignof(::NcmProgramLocation), "ProgramLocation Libnx Compatibility");
#endif
}

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/>.
*/
#pragma once
#include <stratosphere/os.hpp>
#include <stratosphere/ncm/ncm_content_id.hpp>
#include <stratosphere/ncm/ncm_path.hpp>
namespace ams::ncm {
class RegisteredHostContent {
NON_COPYABLE(RegisteredHostContent);
NON_MOVEABLE(RegisteredHostContent);
private:
class RegisteredPath;
private:
using RegisteredPathList = ams::util::IntrusiveListBaseTraits<RegisteredPath>::ListType;
private:
os::SdkMutex m_mutex;
RegisteredPathList m_path_list;
public:
RegisteredHostContent() : m_mutex(), m_path_list() { /* ... */ }
~RegisteredHostContent();
Result RegisterPath(const ncm::ContentId &content_id, const ncm::Path &path);
Result GetPath(Path *out, const ncm::ContentId &content_id);
void ClearPaths();
};
}

View File

@@ -1,41 +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 <vapours.hpp>
#include <stratosphere/fs/fs_rights_id.hpp>
namespace ams::ncm {
struct RightsId {
fs::RightsId id;
u8 key_generation;
u8 reserved[7];
};
static_assert(sizeof(RightsId) == 0x18);
static_assert(util::is_pod<RightsId>::value);
inline bool operator==(const RightsId &lhs, const RightsId &rhs) {
return std::tie(lhs.id, lhs.key_generation) == std::tie(rhs.id, rhs.key_generation);
}
inline bool operator!=(const RightsId &lhs, const RightsId &rhs) {
return !(lhs == rhs);
}
inline bool operator<(const RightsId &lhs, const RightsId &rhs) {
return std::tie(lhs.id, lhs.key_generation) < std::tie(rhs.id, rhs.key_generation);
}
}

View File

@@ -1,90 +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/os.hpp>
#include <stratosphere/ncm/ncm_rights_id.hpp>
#include <stratosphere/ncm/ncm_content_id.hpp>
namespace ams::ncm {
class RightsIdCache {
NON_COPYABLE(RightsIdCache);
NON_MOVEABLE(RightsIdCache);
private:
static constexpr size_t MaxEntries = 0x80;
private:
struct Entry {
public:
util::Uuid uuid;
ncm::RightsId rights_id;
u64 last_accessed;
};
private:
Entry m_entries[MaxEntries];
u64 m_counter;
os::SdkMutex m_mutex;
public:
RightsIdCache() : m_entries(), m_counter(2), m_mutex() {
this->Invalidate();
}
void Invalidate() {
m_counter = 2;
for (size_t i = 0; i < MaxEntries; i++) {
m_entries[i].last_accessed = 1;
}
}
void Store(ContentId content_id, ncm::RightsId rights_id) {
std::scoped_lock lk(m_mutex);
Entry *eviction_candidate = std::addressof(m_entries[0]);
/* Find a suitable existing entry to store our new one at. */
for (size_t i = 1; i < MaxEntries; i++) {
Entry *entry = std::addressof(m_entries[i]);
/* Change eviction candidates if the uuid already matches ours, or if the uuid doesn't already match and the last_accessed count is lower */
if (content_id == entry->uuid || (content_id != eviction_candidate->uuid && entry->last_accessed < eviction_candidate->last_accessed)) {
eviction_candidate = entry;
}
}
/* Update the cache. */
eviction_candidate->uuid = content_id.uuid;
eviction_candidate->rights_id = rights_id;
eviction_candidate->last_accessed = m_counter++;
}
bool Find(ncm::RightsId *out_rights_id, ContentId content_id) {
std::scoped_lock lk(m_mutex);
/* Attempt to locate the content id in the cache. */
for (size_t i = 0; i < MaxEntries; i++) {
Entry *entry = std::addressof(m_entries[i]);
if (entry->last_accessed != 1 && content_id == entry->uuid) {
entry->last_accessed = m_counter;
m_counter++;
*out_rights_id = entry->rights_id;
return true;
}
}
return false;
}
};
}

View File

@@ -1,44 +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 <vapours.hpp>
namespace ams::ncm {
enum class StorageId : u8 {
None = 0,
Host = 1,
GameCard = 2,
BuiltInSystem = 3,
BuiltInUser = 4,
SdCard = 5,
Any = 6,
/* Aliases. */
Card = GameCard,
BuildInSystem = BuiltInSystem,
BuildInUser = BuiltInUser,
};
constexpr inline bool IsUniqueStorage(StorageId id) {
return id != StorageId::None && id != StorageId::Any;
}
constexpr inline bool IsInstallableStorage(StorageId id) {
return id == StorageId::BuiltInSystem || id == StorageId::BuiltInUser || id == StorageId::SdCard || id == StorageId::Any;
}
}

View File

@@ -1,76 +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/ncm/ncm_storage_id.hpp>
#include <stratosphere/ncm/ncm_content_meta_id.hpp>
namespace ams::ncm {
class StorageList {
public:
static constexpr s32 MaxCount = 10;
private:
StorageId m_ids[MaxCount];
s32 m_count;
public:
constexpr StorageList() : m_ids(), m_count() { /* ... */ }
void Push(StorageId storage_id) {
AMS_ABORT_UNLESS(m_count < MaxCount);
for (s32 i = 0; i < MaxCount; i++) {
if (m_ids[i] == storage_id) {
return;
}
}
m_ids[m_count++] = storage_id;
}
s32 Count() const {
return m_count;
}
StorageId operator[](s32 i) const {
AMS_ABORT_UNLESS(i < m_count);
return m_ids[i];
}
};
constexpr StorageList GetStorageList(StorageId storage_id) {
StorageList list;
switch (storage_id) {
case StorageId::BuiltInSystem:
case StorageId::BuiltInUser:
case StorageId::SdCard:
list.Push(storage_id);
break;
case StorageId::Any:
list.Push(StorageId::SdCard);
list.Push(StorageId::BuiltInUser);
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
return list;
}
Result SelectDownloadableStorage(StorageId *out_storage_id, StorageId storage_id, s64 required_size);
Result SelectPatchStorage(StorageId *out_storage_id, StorageId storage_id, PatchId patch_id);
const char *GetStorageIdString(StorageId storage_id);
const char *GetStorageIdStringForPlayReport(StorageId storage_id);
}

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/fs/common/fs_file_storage.hpp>
#include <stratosphere/ncm/ncm_package_install_task.hpp>
namespace ams::ncm {
class SubmissionPackageInstallTask : public PackageInstallTask {
private:
class Impl;
private:
std::unique_ptr<Impl> m_impl;
public:
SubmissionPackageInstallTask();
virtual ~SubmissionPackageInstallTask() override;
Result Initialize(fs::FileHandle handle, StorageId storage_id, void *buffer, size_t buffer_size, bool ignore_ticket = false);
};
}

View File

@@ -1,588 +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/ncm/ncm_data_id.hpp>
#include <stratosphere/ncm/ncm_program_id.hpp>
namespace ams::ncm {
struct SystemProgramId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
static const SystemProgramId Start;
static const SystemProgramId Fs;
static const SystemProgramId Loader;
static const SystemProgramId Ncm;
static const SystemProgramId Pm;
static const SystemProgramId Sm;
static const SystemProgramId Boot;
static const SystemProgramId Usb;
static const SystemProgramId Tma;
static const SystemProgramId Boot2;
static const SystemProgramId Settings;
static const SystemProgramId Bus;
static const SystemProgramId Bluetooth;
static const SystemProgramId Bcat;
static const SystemProgramId Dmnt;
static const SystemProgramId Friends;
static const SystemProgramId Nifm;
static const SystemProgramId Ptm;
static const SystemProgramId Shell;
static const SystemProgramId BsdSockets;
static const SystemProgramId Hid;
static const SystemProgramId Audio;
static const SystemProgramId LogManager;
static const SystemProgramId Wlan;
static const SystemProgramId Cs;
static const SystemProgramId Ldn;
static const SystemProgramId NvServices;
static const SystemProgramId Pcv;
static const SystemProgramId Ppc;
static const SystemProgramId NvnFlinger;
static const SystemProgramId Pcie;
static const SystemProgramId Account;
static const SystemProgramId Ns;
static const SystemProgramId Nfc;
static const SystemProgramId Psc;
static const SystemProgramId CapSrv;
static const SystemProgramId Am;
static const SystemProgramId Ssl;
static const SystemProgramId Nim;
static const SystemProgramId Cec;
static const SystemProgramId Tspm;
static const SystemProgramId Spl;
static const SystemProgramId Lbl;
static const SystemProgramId Btm;
static const SystemProgramId Erpt;
static const SystemProgramId Time;
static const SystemProgramId Vi;
static const SystemProgramId Pctl;
static const SystemProgramId Npns;
static const SystemProgramId Eupld;
static const SystemProgramId Arp;
static const SystemProgramId Glue;
static const SystemProgramId Eclct;
static const SystemProgramId Es;
static const SystemProgramId Fatal;
static const SystemProgramId Grc;
static const SystemProgramId Creport;
static const SystemProgramId Ro;
static const SystemProgramId Profiler;
static const SystemProgramId Sdb;
static const SystemProgramId Migration;
static const SystemProgramId Jit;
static const SystemProgramId JpegDec;
static const SystemProgramId SafeMode;
static const SystemProgramId Olsc;
static const SystemProgramId Dt;
static const SystemProgramId Nd;
static const SystemProgramId Ngct;
static const SystemProgramId Pgl;
static const SystemProgramId Omm;
static const SystemProgramId Eth;
static const SystemProgramId Ngc;
static const SystemProgramId End;
static const SystemProgramId Manu;
static const SystemProgramId Htc;
static const SystemProgramId DmntGen2;
static const SystemProgramId DevServer;
};
struct AtmosphereProgramId {
u64 value;
constexpr operator SystemProgramId() const {
return { this->value };
}
constexpr operator ProgramId() const {
return static_cast<SystemProgramId>(*this);
}
static const AtmosphereProgramId Mitm;
static const AtmosphereProgramId AtmosphereLogManager;
static const AtmosphereProgramId AtmosphereMemlet;
};
inline constexpr const AtmosphereProgramId AtmosphereProgramId::Mitm = { 0x010041544D530000ul };
inline constexpr const AtmosphereProgramId AtmosphereProgramId::AtmosphereLogManager = { 0x0100000000000420ul };
inline constexpr const AtmosphereProgramId AtmosphereProgramId::AtmosphereMemlet = { 0x0100000000000421ul };
inline constexpr bool IsAtmosphereProgramId(const ProgramId &program_id) {
return program_id == AtmosphereProgramId::Mitm || program_id == AtmosphereProgramId::AtmosphereLogManager || program_id == AtmosphereProgramId::AtmosphereMemlet;
}
inline constexpr bool IsSystemProgramId(const AtmosphereProgramId &) {
return true;
}
inline constexpr const SystemProgramId SystemProgramId::Start = { 0x0100000000000000ul };
inline constexpr const SystemProgramId SystemProgramId::Fs = { 0x0100000000000000ul };
inline constexpr const SystemProgramId SystemProgramId::Loader = { 0x0100000000000001ul };
inline constexpr const SystemProgramId SystemProgramId::Ncm = { 0x0100000000000002ul };
inline constexpr const SystemProgramId SystemProgramId::Pm = { 0x0100000000000003ul };
inline constexpr const SystemProgramId SystemProgramId::Sm = { 0x0100000000000004ul };
inline constexpr const SystemProgramId SystemProgramId::Boot = { 0x0100000000000005ul };
inline constexpr const SystemProgramId SystemProgramId::Usb = { 0x0100000000000006ul };
inline constexpr const SystemProgramId SystemProgramId::Tma = { 0x0100000000000007ul };
inline constexpr const SystemProgramId SystemProgramId::Boot2 = { 0x0100000000000008ul };
inline constexpr const SystemProgramId SystemProgramId::Settings = { 0x0100000000000009ul };
inline constexpr const SystemProgramId SystemProgramId::Bus = { 0x010000000000000Aul };
inline constexpr const SystemProgramId SystemProgramId::Bluetooth = { 0x010000000000000Bul };
inline constexpr const SystemProgramId SystemProgramId::Bcat = { 0x010000000000000Cul };
inline constexpr const SystemProgramId SystemProgramId::Dmnt = { 0x010000000000000Dul };
inline constexpr const SystemProgramId SystemProgramId::Friends = { 0x010000000000000Eul };
inline constexpr const SystemProgramId SystemProgramId::Nifm = { 0x010000000000000Ful };
inline constexpr const SystemProgramId SystemProgramId::Ptm = { 0x0100000000000010ul };
inline constexpr const SystemProgramId SystemProgramId::Shell = { 0x0100000000000011ul };
inline constexpr const SystemProgramId SystemProgramId::BsdSockets = { 0x0100000000000012ul };
inline constexpr const SystemProgramId SystemProgramId::Hid = { 0x0100000000000013ul };
inline constexpr const SystemProgramId SystemProgramId::Audio = { 0x0100000000000014ul };
inline constexpr const SystemProgramId SystemProgramId::LogManager = { 0x0100000000000015ul };
inline constexpr const SystemProgramId SystemProgramId::Wlan = { 0x0100000000000016ul };
inline constexpr const SystemProgramId SystemProgramId::Cs = { 0x0100000000000017ul };
inline constexpr const SystemProgramId SystemProgramId::Ldn = { 0x0100000000000018ul };
inline constexpr const SystemProgramId SystemProgramId::NvServices = { 0x0100000000000019ul };
inline constexpr const SystemProgramId SystemProgramId::Pcv = { 0x010000000000001Aul };
inline constexpr const SystemProgramId SystemProgramId::Ppc = { 0x010000000000001Bul };
inline constexpr const SystemProgramId SystemProgramId::NvnFlinger = { 0x010000000000001Cul };
inline constexpr const SystemProgramId SystemProgramId::Pcie = { 0x010000000000001Dul };
inline constexpr const SystemProgramId SystemProgramId::Account = { 0x010000000000001Eul };
inline constexpr const SystemProgramId SystemProgramId::Ns = { 0x010000000000001Ful };
inline constexpr const SystemProgramId SystemProgramId::Nfc = { 0x0100000000000020ul };
inline constexpr const SystemProgramId SystemProgramId::Psc = { 0x0100000000000021ul };
inline constexpr const SystemProgramId SystemProgramId::CapSrv = { 0x0100000000000022ul };
inline constexpr const SystemProgramId SystemProgramId::Am = { 0x0100000000000023ul };
inline constexpr const SystemProgramId SystemProgramId::Ssl = { 0x0100000000000024ul };
inline constexpr const SystemProgramId SystemProgramId::Nim = { 0x0100000000000025ul };
inline constexpr const SystemProgramId SystemProgramId::Cec = { 0x0100000000000026ul };
inline constexpr const SystemProgramId SystemProgramId::Tspm = { 0x0100000000000027ul };
inline constexpr const SystemProgramId SystemProgramId::Spl = { 0x0100000000000028ul };
inline constexpr const SystemProgramId SystemProgramId::Lbl = { 0x0100000000000029ul };
inline constexpr const SystemProgramId SystemProgramId::Btm = { 0x010000000000002Aul };
inline constexpr const SystemProgramId SystemProgramId::Erpt = { 0x010000000000002Bul };
inline constexpr const SystemProgramId SystemProgramId::Time = { 0x010000000000002Cul };
inline constexpr const SystemProgramId SystemProgramId::Vi = { 0x010000000000002Dul };
inline constexpr const SystemProgramId SystemProgramId::Pctl = { 0x010000000000002Eul };
inline constexpr const SystemProgramId SystemProgramId::Npns = { 0x010000000000002Ful };
inline constexpr const SystemProgramId SystemProgramId::Eupld = { 0x0100000000000030ul };
inline constexpr const SystemProgramId SystemProgramId::Arp = { 0x0100000000000031ul };
inline constexpr const SystemProgramId SystemProgramId::Glue = { 0x0100000000000031ul };
inline constexpr const SystemProgramId SystemProgramId::Eclct = { 0x0100000000000032ul };
inline constexpr const SystemProgramId SystemProgramId::Es = { 0x0100000000000033ul };
inline constexpr const SystemProgramId SystemProgramId::Fatal = { 0x0100000000000034ul };
inline constexpr const SystemProgramId SystemProgramId::Grc = { 0x0100000000000035ul };
inline constexpr const SystemProgramId SystemProgramId::Creport = { 0x0100000000000036ul };
inline constexpr const SystemProgramId SystemProgramId::Ro = { 0x0100000000000037ul };
inline constexpr const SystemProgramId SystemProgramId::Profiler = { 0x0100000000000038ul };
inline constexpr const SystemProgramId SystemProgramId::Sdb = { 0x0100000000000039ul };
inline constexpr const SystemProgramId SystemProgramId::Migration = { 0x010000000000003Aul };
inline constexpr const SystemProgramId SystemProgramId::Jit = { 0x010000000000003Bul };
inline constexpr const SystemProgramId SystemProgramId::JpegDec = { 0x010000000000003Cul };
inline constexpr const SystemProgramId SystemProgramId::SafeMode = { 0x010000000000003Dul };
inline constexpr const SystemProgramId SystemProgramId::Olsc = { 0x010000000000003Eul };
inline constexpr const SystemProgramId SystemProgramId::Dt = { 0x010000000000003Ful };
inline constexpr const SystemProgramId SystemProgramId::Nd = { 0x0100000000000040ul };
inline constexpr const SystemProgramId SystemProgramId::Ngct = { 0x0100000000000041ul };
inline constexpr const SystemProgramId SystemProgramId::Pgl = { 0x0100000000000042ul };
inline constexpr const SystemProgramId SystemProgramId::Omm = { 0x0100000000000045ul };
inline constexpr const SystemProgramId SystemProgramId::Eth = { 0x0100000000000046ul };
inline constexpr const SystemProgramId SystemProgramId::Ngc = { 0x0100000000000050ul };
inline constexpr const SystemProgramId SystemProgramId::End = { 0x01000000000007FFul };
inline constexpr const SystemProgramId SystemProgramId::Manu = { 0x010000000000B14Aul };
inline constexpr const SystemProgramId SystemProgramId::Htc = { 0x010000000000B240ul };
inline constexpr const SystemProgramId SystemProgramId::DmntGen2 = { 0x010000000000D609ul };
inline constexpr const SystemProgramId SystemProgramId::DevServer = { 0x010000000000D623ul };
inline constexpr bool IsSystemProgramId(const ProgramId &program_id) {
return (SystemProgramId::Start <= program_id && program_id <= SystemProgramId::End) || IsAtmosphereProgramId(program_id);
}
inline constexpr bool IsSystemProgramId(const SystemProgramId &) {
return true;
}
struct SystemDataId {
u64 value;
constexpr operator DataId() const {
return { this->value };
}
constexpr inline bool operator==(const SystemDataId &) const = default;
constexpr inline bool operator!=(const SystemDataId &) const = default;
static const SystemDataId Start;
static const SystemDataId CertStore;
static const SystemDataId ErrorMessage;
static const SystemDataId MiiModel;
static const SystemDataId BrowserDll;
static const SystemDataId Help;
static const SystemDataId SharedFont;
static const SystemDataId NgWord;
static const SystemDataId SsidList;
static const SystemDataId Dictionary;
static const SystemDataId SystemVersion;
static const SystemDataId AvatarImage;
static const SystemDataId LocalNews;
static const SystemDataId Eula;
static const SystemDataId UrlBlackList;
static const SystemDataId TimeZoneBinar;
static const SystemDataId CertStoreCruiser;
static const SystemDataId FontNintendoExtension;
static const SystemDataId FontStandard;
static const SystemDataId FontKorean;
static const SystemDataId FontChineseTraditional;
static const SystemDataId FontChineseSimple;
static const SystemDataId FontBfcpx;
static const SystemDataId SystemUpdate;
static const SystemDataId FirmwareDebugSettings;
static const SystemDataId BootImagePackage;
static const SystemDataId BootImagePackageSafe;
static const SystemDataId BootImagePackageExFat;
static const SystemDataId BootImagePackageExFatSafe;
static const SystemDataId FatalMessage;
static const SystemDataId ControllerIcon;
static const SystemDataId PlatformConfigIcosa;
static const SystemDataId PlatformConfigCopper;
static const SystemDataId PlatformConfigHoag;
static const SystemDataId ControllerFirmware;
static const SystemDataId NgWord2;
static const SystemDataId PlatformConfigIcosaMariko;
static const SystemDataId ApplicationBlackList;
static const SystemDataId RebootlessSystemUpdateVersion;
static const SystemDataId ContentActionTable;
static const SystemDataId PlatformConfigCalcio;
static const SystemDataId PlatformConfigAula;
static const SystemDataId End;
};
inline constexpr const SystemDataId SystemDataId::Start = { 0x0100000000000800ul };
inline constexpr const SystemDataId SystemDataId::CertStore = { 0x0100000000000800ul };
inline constexpr const SystemDataId SystemDataId::ErrorMessage = { 0x0100000000000801ul };
inline constexpr const SystemDataId SystemDataId::MiiModel = { 0x0100000000000802ul };
inline constexpr const SystemDataId SystemDataId::BrowserDll = { 0x0100000000000803ul };
inline constexpr const SystemDataId SystemDataId::Help = { 0x0100000000000804ul };
inline constexpr const SystemDataId SystemDataId::SharedFont = { 0x0100000000000805ul };
inline constexpr const SystemDataId SystemDataId::NgWord = { 0x0100000000000806ul };
inline constexpr const SystemDataId SystemDataId::SsidList = { 0x0100000000000807ul };
inline constexpr const SystemDataId SystemDataId::Dictionary = { 0x0100000000000808ul };
inline constexpr const SystemDataId SystemDataId::SystemVersion = { 0x0100000000000809ul };
inline constexpr const SystemDataId SystemDataId::AvatarImage = { 0x010000000000080Aul };
inline constexpr const SystemDataId SystemDataId::LocalNews = { 0x010000000000080Bul };
inline constexpr const SystemDataId SystemDataId::Eula = { 0x010000000000080Cul };
inline constexpr const SystemDataId SystemDataId::UrlBlackList = { 0x010000000000080Dul };
inline constexpr const SystemDataId SystemDataId::TimeZoneBinar = { 0x010000000000080Eul };
inline constexpr const SystemDataId SystemDataId::CertStoreCruiser = { 0x010000000000080Ful };
inline constexpr const SystemDataId SystemDataId::FontNintendoExtension = { 0x0100000000000810ul };
inline constexpr const SystemDataId SystemDataId::FontStandard = { 0x0100000000000811ul };
inline constexpr const SystemDataId SystemDataId::FontKorean = { 0x0100000000000812ul };
inline constexpr const SystemDataId SystemDataId::FontChineseTraditional = { 0x0100000000000813ul };
inline constexpr const SystemDataId SystemDataId::FontChineseSimple = { 0x0100000000000814ul };
inline constexpr const SystemDataId SystemDataId::FontBfcpx = { 0x0100000000000815ul };
inline constexpr const SystemDataId SystemDataId::SystemUpdate = { 0x0100000000000816ul };
inline constexpr const SystemDataId SystemDataId::FirmwareDebugSettings = { 0x0100000000000818ul };
inline constexpr const SystemDataId SystemDataId::BootImagePackage = { 0x0100000000000819ul };
inline constexpr const SystemDataId SystemDataId::BootImagePackageSafe = { 0x010000000000081Aul };
inline constexpr const SystemDataId SystemDataId::BootImagePackageExFat = { 0x010000000000081Bul };
inline constexpr const SystemDataId SystemDataId::BootImagePackageExFatSafe = { 0x010000000000081Cul };
inline constexpr const SystemDataId SystemDataId::FatalMessage = { 0x010000000000081Dul };
inline constexpr const SystemDataId SystemDataId::ControllerIcon = { 0x010000000000081Eul };
inline constexpr const SystemDataId SystemDataId::PlatformConfigIcosa = { 0x010000000000081Ful };
inline constexpr const SystemDataId SystemDataId::PlatformConfigCopper = { 0x0100000000000820ul };
inline constexpr const SystemDataId SystemDataId::PlatformConfigHoag = { 0x0100000000000821ul };
inline constexpr const SystemDataId SystemDataId::ControllerFirmware = { 0x0100000000000822ul };
inline constexpr const SystemDataId SystemDataId::NgWord2 = { 0x0100000000000823ul };
inline constexpr const SystemDataId SystemDataId::PlatformConfigIcosaMariko = { 0x0100000000000824ul };
inline constexpr const SystemDataId SystemDataId::ApplicationBlackList = { 0x0100000000000825ul };
inline constexpr const SystemDataId SystemDataId::RebootlessSystemUpdateVersion = { 0x0100000000000826ul };
inline constexpr const SystemDataId SystemDataId::ContentActionTable = { 0x0100000000000827ul };
inline constexpr const SystemDataId SystemDataId::PlatformConfigCalcio = { 0x0100000000000829ul };
inline constexpr const SystemDataId SystemDataId::PlatformConfigAula = { 0x0100000000000831ul };
inline constexpr const SystemDataId SystemDataId::End = { 0x0100000000000FFFul };
inline constexpr bool IsSystemDataId(const DataId &data_id) {
return SystemDataId::Start <= data_id && data_id <= SystemDataId::End;
}
inline constexpr bool IsSystemDataId(const SystemDataId &) {
return true;
}
struct SystemUpdateId {
u64 value;
constexpr operator DataId() const {
return { this->value };
}
constexpr inline bool operator==(const SystemUpdateId &) const = default;
constexpr inline bool operator!=(const SystemUpdateId &) const = default;
};
struct SystemAppletId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const SystemAppletId &) const = default;
constexpr inline bool operator!=(const SystemAppletId &) const = default;
static const SystemAppletId Start;
static const SystemAppletId Qlaunch;
static const SystemAppletId Auth;
static const SystemAppletId Cabinet;
static const SystemAppletId Controller;
static const SystemAppletId DataErase;
static const SystemAppletId Error;
static const SystemAppletId NetConnect;
static const SystemAppletId PlayerSelect;
static const SystemAppletId Swkbd;
static const SystemAppletId MiiEdit;
static const SystemAppletId Web;
static const SystemAppletId Shop;
static const SystemAppletId OverlayDisp;
static const SystemAppletId PhotoViewer;
static const SystemAppletId Set;
static const SystemAppletId OfflineWeb;
static const SystemAppletId LoginShare;
static const SystemAppletId WifiWebAuth;
static const SystemAppletId Starter;
static const SystemAppletId MyPage;
static const SystemAppletId PlayReport;
static const SystemAppletId MaintenanceMenu;
static const SystemAppletId Gift;
static const SystemAppletId DummyShop;
static const SystemAppletId UserMigration;
static const SystemAppletId Encounter;
static const SystemAppletId Story;
static const SystemAppletId End;
};
inline constexpr const SystemAppletId SystemAppletId::Start = { 0x0100000000001000ul };
inline constexpr const SystemAppletId SystemAppletId::Qlaunch = { 0x0100000000001000ul };
inline constexpr const SystemAppletId SystemAppletId::Auth = { 0x0100000000001001ul };
inline constexpr const SystemAppletId SystemAppletId::Cabinet = { 0x0100000000001002ul };
inline constexpr const SystemAppletId SystemAppletId::Controller = { 0x0100000000001003ul };
inline constexpr const SystemAppletId SystemAppletId::DataErase = { 0x0100000000001004ul };
inline constexpr const SystemAppletId SystemAppletId::Error = { 0x0100000000001005ul };
inline constexpr const SystemAppletId SystemAppletId::NetConnect = { 0x0100000000001006ul };
inline constexpr const SystemAppletId SystemAppletId::PlayerSelect = { 0x0100000000001007ul };
inline constexpr const SystemAppletId SystemAppletId::Swkbd = { 0x0100000000001008ul };
inline constexpr const SystemAppletId SystemAppletId::MiiEdit = { 0x0100000000001009ul };
inline constexpr const SystemAppletId SystemAppletId::Web = { 0x010000000000100Aul };
inline constexpr const SystemAppletId SystemAppletId::Shop = { 0x010000000000100Bul };
inline constexpr const SystemAppletId SystemAppletId::OverlayDisp = { 0x010000000000100Cul };
inline constexpr const SystemAppletId SystemAppletId::PhotoViewer = { 0x010000000000100Dul };
inline constexpr const SystemAppletId SystemAppletId::Set = { 0x010000000000100Eul };
inline constexpr const SystemAppletId SystemAppletId::OfflineWeb = { 0x010000000000100Ful };
inline constexpr const SystemAppletId SystemAppletId::LoginShare = { 0x0100000000001010ul };
inline constexpr const SystemAppletId SystemAppletId::WifiWebAuth = { 0x0100000000001011ul };
inline constexpr const SystemAppletId SystemAppletId::Starter = { 0x0100000000001012ul };
inline constexpr const SystemAppletId SystemAppletId::MyPage = { 0x0100000000001013ul };
inline constexpr const SystemAppletId SystemAppletId::PlayReport = { 0x0100000000001014ul };
inline constexpr const SystemAppletId SystemAppletId::MaintenanceMenu = { 0x0100000000001015ul };
inline constexpr const SystemAppletId SystemAppletId::Gift = { 0x010000000000101Aul };
inline constexpr const SystemAppletId SystemAppletId::DummyShop = { 0x010000000000101Bul };
inline constexpr const SystemAppletId SystemAppletId::UserMigration = { 0x010000000000101Cul };
inline constexpr const SystemAppletId SystemAppletId::Encounter = { 0x010000000000101Dul };
inline constexpr const SystemAppletId SystemAppletId::Story = { 0x0100000000001020ul };
inline constexpr const SystemAppletId SystemAppletId::End = { 0x0100000000001FFFul };
inline constexpr bool IsSystemAppletId(const ProgramId &program_id) {
return SystemAppletId::Start <= program_id && program_id <= SystemAppletId::End;
}
inline constexpr bool IsSystemAppletId(const SystemAppletId &) {
return true;
}
struct SystemDebugAppletId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const SystemDebugAppletId &) const = default;
constexpr inline bool operator!=(const SystemDebugAppletId &) const = default;
static const SystemDebugAppletId Start;
static const SystemDebugAppletId SnapShotDumper;
static const SystemDebugAppletId End;
};
inline constexpr const SystemDebugAppletId SystemDebugAppletId::Start = { 0x0100000000002000ul };
inline constexpr const SystemDebugAppletId SystemDebugAppletId::SnapShotDumper = { 0x0100000000002071ul };
inline constexpr const SystemDebugAppletId SystemDebugAppletId::End = { 0x0100000000002FFFul };
inline constexpr bool IsSystemDebugAppletId(const ProgramId &program_id) {
return SystemDebugAppletId::Start <= program_id && program_id <= SystemDebugAppletId::End;
}
inline constexpr bool IsSystemDebugAppletId(const SystemDebugAppletId &) {
return true;
}
struct LibraryAppletId {
u64 value;
constexpr operator SystemAppletId() const {
return { this->value };
}
constexpr operator ProgramId() const {
return static_cast<SystemAppletId>(*this);
}
constexpr inline bool operator==(const LibraryAppletId &) const = default;
constexpr inline bool operator!=(const LibraryAppletId &) const = default;
static const LibraryAppletId Auth;
static const LibraryAppletId Controller;
static const LibraryAppletId Error;
static const LibraryAppletId PlayerSelect;
static const LibraryAppletId Swkbd;
static const LibraryAppletId Web;
static const LibraryAppletId Shop;
static const LibraryAppletId PhotoViewer;
static const LibraryAppletId OfflineWeb;
static const LibraryAppletId LoginShare;
static const LibraryAppletId WifiWebAuth;
static const LibraryAppletId MyPage;
};
inline constexpr const LibraryAppletId LibraryAppletId::Auth = { SystemAppletId::Auth.value };
inline constexpr const LibraryAppletId LibraryAppletId::Controller = { SystemAppletId::Controller.value };
inline constexpr const LibraryAppletId LibraryAppletId::Error = { SystemAppletId::Error.value };
inline constexpr const LibraryAppletId LibraryAppletId::PlayerSelect = { SystemAppletId::PlayerSelect.value };
inline constexpr const LibraryAppletId LibraryAppletId::Swkbd = { SystemAppletId::Swkbd.value };
inline constexpr const LibraryAppletId LibraryAppletId::Web = { SystemAppletId::Web.value };
inline constexpr const LibraryAppletId LibraryAppletId::Shop = { SystemAppletId::Shop.value };
inline constexpr const LibraryAppletId LibraryAppletId::PhotoViewer = { SystemAppletId::PhotoViewer.value };
inline constexpr const LibraryAppletId LibraryAppletId::OfflineWeb = { SystemAppletId::OfflineWeb.value };
inline constexpr const LibraryAppletId LibraryAppletId::LoginShare = { SystemAppletId::LoginShare.value };
inline constexpr const LibraryAppletId LibraryAppletId::WifiWebAuth = { SystemAppletId::WifiWebAuth.value };
inline constexpr const LibraryAppletId LibraryAppletId::MyPage = { SystemAppletId::MyPage.value };
inline constexpr bool IsLibraryAppletId(const ProgramId &id) {
return id == LibraryAppletId::Auth ||
id == LibraryAppletId::Controller ||
id == LibraryAppletId::Error ||
id == LibraryAppletId::PlayerSelect ||
id == LibraryAppletId::Swkbd ||
id == LibraryAppletId::Web ||
id == LibraryAppletId::Shop ||
id == LibraryAppletId::PhotoViewer ||
id == LibraryAppletId::OfflineWeb ||
id == LibraryAppletId::LoginShare ||
id == LibraryAppletId::WifiWebAuth ||
id == LibraryAppletId::MyPage;
}
inline constexpr bool IsLibraryAppletId(const LibraryAppletId &) {
return true;
}
struct WebAppletId {
u64 value;
constexpr operator LibraryAppletId() const {
return { this->value };
}
constexpr operator SystemAppletId() const {
return static_cast<LibraryAppletId>(*this);
}
constexpr operator ProgramId() const {
return static_cast<SystemAppletId>(*this);
}
constexpr inline bool operator==(const WebAppletId &) const = default;
constexpr inline bool operator!=(const WebAppletId &) const = default;
static const WebAppletId Web;
static const WebAppletId Shop;
static const WebAppletId OfflineWeb;
static const WebAppletId LoginShare;
static const WebAppletId WifiWebAuth;
};
inline constexpr const WebAppletId WebAppletId::Web = { LibraryAppletId::Web.value };
inline constexpr const WebAppletId WebAppletId::Shop = { LibraryAppletId::Shop.value };
inline constexpr const WebAppletId WebAppletId::OfflineWeb = { LibraryAppletId::OfflineWeb.value };
inline constexpr const WebAppletId WebAppletId::LoginShare = { LibraryAppletId::LoginShare.value };
inline constexpr const WebAppletId WebAppletId::WifiWebAuth = { LibraryAppletId::WifiWebAuth.value };
inline constexpr bool IsWebAppletId(const ProgramId &id) {
return id == WebAppletId::Web ||
id == WebAppletId::Shop ||
id == WebAppletId::OfflineWeb ||
id == WebAppletId::LoginShare ||
id == WebAppletId::WifiWebAuth;
}
inline constexpr bool IsWebAppletId(const WebAppletId &) {
return true;
}
struct SystemApplicationId {
u64 value;
constexpr operator ProgramId() const {
return { this->value };
}
constexpr inline bool operator==(const SystemApplicationId &) const = default;
constexpr inline bool operator!=(const SystemApplicationId &) const = default;
};
}

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 <vapours.hpp>
namespace ams::ncm {
enum class SystemUpdateTaskApplyInfo : u8 {
Unknown = 0,
RequireReboot = 1,
RequireNoReboot = 2,
};
}