mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
ncm: update to 10.0.0 (#879)
This commit is contained in:
parent
116e00c21c
commit
a25be61e94
12 changed files with 243 additions and 7 deletions
|
@ -33,6 +33,7 @@
|
|||
#include <stratosphere/ncm/ncm_install_task_base.hpp>
|
||||
#include <stratosphere/ncm/ncm_install_task_data.hpp>
|
||||
#include <stratosphere/ncm/ncm_install_task_occupied_size.hpp>
|
||||
#include <stratosphere/ncm/ncm_memory_report.hpp>
|
||||
#include <stratosphere/ncm/ncm_package_install_task_base.hpp>
|
||||
#include <stratosphere/ncm/ncm_package_install_task.hpp>
|
||||
#include <stratosphere/ncm/ncm_package_system_update_task.hpp>
|
||||
|
|
|
@ -30,14 +30,32 @@
|
|||
|
||||
namespace ams::ncm {
|
||||
|
||||
class ContentMetaMemoryResource {
|
||||
class ContentMetaMemoryResource : public MemoryResource {
|
||||
private:
|
||||
mem::StandardAllocator allocator;
|
||||
sf::StandardAllocatorMemoryResource memory_resource;
|
||||
size_t peak_total_alloc_size;
|
||||
size_t peak_alloc_size;
|
||||
public:
|
||||
ContentMetaMemoryResource(void *heap, size_t heap_size) : allocator(heap, heap_size), memory_resource(std::addressof(allocator)) { /* ... */ }
|
||||
explicit ContentMetaMemoryResource(void *heap, size_t heap_size) : allocator(heap, heap_size) { /* ... */ }
|
||||
|
||||
MemoryResource *Get() { return std::addressof(this->memory_resource); }
|
||||
mem::StandardAllocator *GetAllocator() { return std::addressof(this->allocator); }
|
||||
size_t GetPeakTotalAllocationSize() const { return this->peak_total_alloc_size; }
|
||||
size_t GetPeakAllocationSize() const { return this->peak_alloc_size; }
|
||||
private:
|
||||
virtual void *AllocateImpl(size_t size, size_t alignment) override {
|
||||
void *mem = this->allocator.Allocate(size, alignment);
|
||||
this->peak_total_alloc_size = std::max(this->allocator.Hash().allocated_size, this->peak_total_alloc_size);
|
||||
this->peak_alloc_size = std::max(size, this->peak_alloc_size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
virtual void DeallocateImpl(void *buffer, size_t size, size_t alignment) override {
|
||||
return this->allocator.Free(buffer);
|
||||
}
|
||||
|
||||
virtual bool IsEqualImpl(const MemoryResource &resource) const override {
|
||||
return this == std::addressof(resource);
|
||||
}
|
||||
};
|
||||
|
||||
struct SystemSaveDataInfo {
|
||||
|
@ -127,6 +145,7 @@ namespace ams::ncm {
|
|||
virtual Result ActivateContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result InactivateContentMetaDatabase(StorageId storage_id) override;
|
||||
virtual Result InvalidateRightsIdCache() override;
|
||||
virtual Result GetMemoryReport(sf::Out<MemoryReport> out) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#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>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
|
@ -36,6 +37,7 @@ namespace ams::ncm {
|
|||
ActivateContentMetaDatabase = 11,
|
||||
InactivateContentMetaDatabase = 12,
|
||||
InvalidateRightsIdCache = 13,
|
||||
GetMemoryReport = 14,
|
||||
};
|
||||
public:
|
||||
virtual Result CreateContentStorage(StorageId storage_id) = 0;
|
||||
|
@ -52,6 +54,7 @@ namespace ams::ncm {
|
|||
virtual Result ActivateContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result InactivateContentMetaDatabase(StorageId storage_id) = 0;
|
||||
virtual Result InvalidateRightsIdCache() = 0;
|
||||
virtual Result GetMemoryReport(sf::Out<MemoryReport> out) = 0;
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(CreateContentStorage),
|
||||
|
@ -68,6 +71,7 @@ namespace ams::ncm {
|
|||
MAKE_SERVICE_COMMAND_META(ActivateContentMetaDatabase, hos::Version_2_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(InactivateContentMetaDatabase, hos::Version_2_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(InvalidateRightsIdCache, hos::Version_9_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(GetMemoryReport, hos::Version_10_0_0),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ namespace ams::ncm {
|
|||
GetAttributes = 18,
|
||||
GetRequiredApplicationVersion = 19,
|
||||
GetContentIdByTypeAndIdOffset = 20,
|
||||
GetCount = 21,
|
||||
GetOwnerApplicationId = 22,
|
||||
};
|
||||
public:
|
||||
/* Actual commands. */
|
||||
|
@ -67,6 +69,8 @@ namespace ams::ncm {
|
|||
virtual Result GetAttributes(sf::Out<u8> out_attributes, const ContentMetaKey &key) = 0;
|
||||
virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) = 0;
|
||||
virtual Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) = 0;
|
||||
virtual Result GetCount(sf::Out<u32> out_count) = 0;
|
||||
virtual Result GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key) = 0;
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
MAKE_SERVICE_COMMAND_META(Set),
|
||||
|
@ -90,6 +94,8 @@ namespace ams::ncm {
|
|||
MAKE_SERVICE_COMMAND_META(GetAttributes),
|
||||
MAKE_SERVICE_COMMAND_META(GetRequiredApplicationVersion, hos::Version_2_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(GetContentIdByTypeAndIdOffset, hos::Version_5_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(GetCount, hos::Version_10_0_0),
|
||||
MAKE_SERVICE_COMMAND_META(GetOwnerApplicationId, hos::Version_10_0_0),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Adubbz, 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::Mutex mutex;
|
||||
lmem::HeapHandle heap_handle;
|
||||
size_t total_alloc_size;
|
||||
size_t peak_total_alloc_size;
|
||||
size_t peak_alloc_size;
|
||||
public:
|
||||
constexpr HeapState() : mutex(false), heap_handle(nullptr), total_alloc_size(0), peak_total_alloc_size(0), 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();
|
||||
|
||||
}
|
|
@ -614,7 +614,7 @@ namespace ams::ncm {
|
|||
|
||||
if (storage_id == StorageId::GameCard) {
|
||||
/* Initialize the key value store. */
|
||||
R_TRY(root->kvs->Initialize(root->max_content_metas, root->memory_resource->Get()));
|
||||
R_TRY(root->kvs->Initialize(root->max_content_metas, root->memory_resource));
|
||||
|
||||
/* Create an on memory content meta database for game cards. */
|
||||
root->content_meta_database = std::make_shared<OnMemoryContentMetaDatabaseImpl>(std::addressof(*root->kvs));
|
||||
|
@ -626,7 +626,7 @@ namespace ams::ncm {
|
|||
auto mount_guard = SCOPE_GUARD { fs::Unmount(root->mount_name); };
|
||||
|
||||
/* Initialize and load the key value store from the filesystem. */
|
||||
R_TRY(root->kvs->Initialize(root->path, root->max_content_metas, root->memory_resource->Get()));
|
||||
R_TRY(root->kvs->Initialize(root->path, root->max_content_metas, root->memory_resource));
|
||||
R_TRY(root->kvs->Load());
|
||||
|
||||
/* Create the content meta database. */
|
||||
|
@ -665,4 +665,36 @@ namespace ams::ncm {
|
|||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentManagerImpl::GetMemoryReport(sf::Out<MemoryReport> out) {
|
||||
/* Populate content meta resource states. */
|
||||
MemoryReport report = {
|
||||
.system_content_meta_resource_state = {
|
||||
.peak_total_alloc_size = g_system_content_meta_memory_resource.GetPeakTotalAllocationSize(),
|
||||
.peak_alloc_size = g_system_content_meta_memory_resource.GetPeakAllocationSize(),
|
||||
.allocatable_size = g_system_content_meta_memory_resource.GetAllocator()->GetAllocatableSize(),
|
||||
.total_free_size = g_system_content_meta_memory_resource.GetAllocator()->GetTotalFreeSize(),
|
||||
},
|
||||
.sd_and_user_content_meta_resource_state {
|
||||
.peak_total_alloc_size = g_sd_and_user_content_meta_memory_resource.GetPeakTotalAllocationSize(),
|
||||
.peak_alloc_size = g_sd_and_user_content_meta_memory_resource.GetPeakAllocationSize(),
|
||||
.allocatable_size = g_sd_and_user_content_meta_memory_resource.GetAllocator()->GetAllocatableSize(),
|
||||
.total_free_size = g_sd_and_user_content_meta_memory_resource.GetAllocator()->GetTotalFreeSize(),
|
||||
},
|
||||
.gamecard_content_meta_resource_state {
|
||||
.peak_total_alloc_size = g_gamecard_content_meta_memory_resource.GetPeakTotalAllocationSize(),
|
||||
.peak_alloc_size = g_gamecard_content_meta_memory_resource.GetPeakAllocationSize(),
|
||||
.allocatable_size = g_gamecard_content_meta_memory_resource.GetAllocator()->GetAllocatableSize(),
|
||||
.total_free_size = g_gamecard_content_meta_memory_resource.GetAllocator()->GetTotalFreeSize(),
|
||||
},
|
||||
.heap_resource_state = {},
|
||||
};
|
||||
|
||||
/* Populate heap memory resource state. */
|
||||
GetHeapState().GetMemoryResourceState(std::addressof(report.heap_resource_state));
|
||||
|
||||
/* Output the report. */
|
||||
out.SetValue(report);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -440,4 +440,47 @@ namespace ams::ncm {
|
|||
return this->GetContentIdImpl(out_content_id.GetPointer(), key, type, std::make_optional(id_offset));
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetCount(sf::Out<u32> out_count) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
out_count.SetValue(this->kvs->GetCount());
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result ContentMetaDatabaseImpl::GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key) {
|
||||
R_TRY(this->EnsureEnabled());
|
||||
|
||||
/* Ensure this type of key has an owner. */
|
||||
R_UNLESS(key.type == ContentMetaType::Application || key.type == ContentMetaType::Patch || key.type == ContentMetaType::AddOnContent, ncm::ResultInvalidContentMetaKey());
|
||||
|
||||
/* Applications are their own owner. */
|
||||
if (key.type == ContentMetaType::Application) {
|
||||
out_id.SetValue({key.id});
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
/* Obtain the content meta for the key. */
|
||||
const void *meta;
|
||||
size_t meta_size;
|
||||
R_TRY(this->GetContentMetaPointer(&meta, &meta_size, key));
|
||||
|
||||
/* Create a reader. */
|
||||
ContentMetaReader reader(meta, meta_size);
|
||||
|
||||
/* Get the owner application id. */
|
||||
ApplicationId owner_application_id;
|
||||
switch (key.type) {
|
||||
case ContentMetaType::Patch:
|
||||
owner_application_id = reader.GetExtendedHeader<PatchMetaExtendedHeader>()->application_id;
|
||||
break;
|
||||
case ContentMetaType::AddOnContent:
|
||||
owner_application_id = reader.GetExtendedHeader<AddOnContentMetaExtendedHeader>()->application_id;
|
||||
break;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
|
||||
/* Set the output value. */
|
||||
out_id.SetValue(owner_application_id);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ namespace ams::ncm {
|
|||
virtual Result GetAttributes(sf::Out<u8> out_attributes, const ContentMetaKey &key) override;
|
||||
virtual Result GetRequiredApplicationVersion(sf::Out<u32> out_version, const ContentMetaKey &key) override;
|
||||
virtual Result GetContentIdByTypeAndIdOffset(sf::Out<ContentId> out_content_id, const ContentMetaKey &key, ContentType type, u8 id_offset) override;
|
||||
virtual Result GetCount(sf::Out<u32> out_count) override;
|
||||
virtual Result GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
51
libraries/libstratosphere/source/ncm/ncm_memory_report.cpp
Normal file
51
libraries/libstratosphere/source/ncm/ncm_memory_report.cpp
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 Adubbz, Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::ncm {
|
||||
|
||||
void HeapState::Initialize(lmem::HeapHandle heap_handle) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
this->heap_handle = heap_handle;
|
||||
}
|
||||
|
||||
void HeapState::Allocate(size_t size) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
this->total_alloc_size += size;
|
||||
this->peak_total_alloc_size = std::max(this->total_alloc_size, this->peak_total_alloc_size);
|
||||
this->peak_alloc_size = std::max(size, this->peak_alloc_size);
|
||||
}
|
||||
|
||||
void HeapState::Free(size_t size) {
|
||||
std::scoped_lock lk(this->mutex);
|
||||
this->total_alloc_size -= size;
|
||||
}
|
||||
|
||||
void HeapState::GetMemoryResourceState(MemoryResourceState *out) {
|
||||
*out = {};
|
||||
std::scoped_lock lk(this->mutex);
|
||||
out->peak_total_alloc_size = this->peak_total_alloc_size;
|
||||
out->peak_alloc_size = this->peak_alloc_size;
|
||||
out->total_free_size = lmem::GetExpHeapTotalFreeSize(this->heap_handle);
|
||||
out->allocatable_size = lmem::GetExpHeapAllocatableSize(this->heap_handle, alignof(s32));
|
||||
}
|
||||
|
||||
HeapState &GetHeapState() {
|
||||
static HeapState s_heap_state = {};
|
||||
return s_heap_state;
|
||||
}
|
||||
|
||||
}
|
|
@ -89,6 +89,11 @@ namespace ams::ncm {
|
|||
virtual Result InvalidateRightsIdCache() override {
|
||||
return ::ncmInvalidateRightsIdCache();
|
||||
}
|
||||
|
||||
virtual Result GetMemoryReport(sf::Out<MemoryReport> out) override {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -156,6 +156,16 @@ namespace ams::ncm {
|
|||
return ncmContentMetaDatabaseGetContentIdByTypeAndIdOffset(std::addressof(this->srv), Convert(out_content_id.GetPointer()), Convert(key), static_cast<::NcmContentType>(type), id_offset);
|
||||
}
|
||||
|
||||
virtual Result GetCount(sf::Out<u32> out_count) override {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
virtual Result GetOwnerApplicationId(sf::Out<ApplicationId> out_id, const ContentMetaKey &key) override {
|
||||
/* TODO: libnx bindings */
|
||||
AMS_ABORT();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -55,15 +55,19 @@ namespace {
|
|||
lmem::HeapHandle g_heap_handle;
|
||||
|
||||
void *Allocate(size_t size) {
|
||||
return lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
void *mem = lmem::AllocateFromExpHeap(g_heap_handle, size);
|
||||
GetHeapState().Allocate(size);
|
||||
return mem;
|
||||
}
|
||||
|
||||
void Deallocate(void *p, size_t size) {
|
||||
GetHeapState().Free(size);
|
||||
lmem::FreeToExpHeap(g_heap_handle, p);
|
||||
}
|
||||
|
||||
void InitializeHeap() {
|
||||
g_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_None);
|
||||
GetHeapState().Initialize(g_heap_handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue