2022-10-12 05:32:56 +01:00
|
|
|
/*
|
|
|
|
* Copyright (c) Atmosphère-NX
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
|
|
* more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
#include <mesosphere.hpp>
|
|
|
|
|
|
|
|
namespace ams::kern {
|
|
|
|
|
|
|
|
Result KSecureSystemResource::Initialize(size_t size, KResourceLimit *resource_limit, KMemoryManager::Pool pool) {
|
|
|
|
/* Set members. */
|
|
|
|
m_resource_limit = resource_limit;
|
|
|
|
m_resource_size = size;
|
|
|
|
m_resource_pool = pool;
|
|
|
|
|
|
|
|
/* Determine required size for our secure resource. */
|
|
|
|
const size_t secure_size = this->CalculateRequiredSecureMemorySize();
|
|
|
|
|
|
|
|
/* Reserve memory for our secure resource. */
|
|
|
|
KScopedResourceReservation memory_reservation(m_resource_limit, ams::svc::LimitableResource_PhysicalMemoryMax, secure_size);
|
|
|
|
R_UNLESS(memory_reservation.Succeeded(), svc::ResultLimitReached());
|
|
|
|
|
|
|
|
/* Allocate secure memory. */
|
|
|
|
R_TRY(KSystemControl::AllocateSecureMemory(std::addressof(m_resource_address), m_resource_size, m_resource_pool));
|
|
|
|
MESOSPHERE_ASSERT(m_resource_address != Null<KVirtualAddress>);
|
|
|
|
|
|
|
|
/* Ensure we clean up the secure memory, if we fail past this point. */
|
|
|
|
ON_RESULT_FAILURE { KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool); };
|
|
|
|
|
|
|
|
/* Check that our allocation is bigger than the reference counts needed for it. */
|
|
|
|
const size_t rc_size = util::AlignUp(KPageTableSlabHeap::CalculateReferenceCountSize(m_resource_size), PageSize);
|
|
|
|
R_UNLESS(m_resource_size > rc_size, svc::ResultOutOfMemory());
|
|
|
|
|
|
|
|
/* Initialize slab heaps. */
|
2022-10-12 07:14:15 +01:00
|
|
|
m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, PageSize);
|
2022-10-12 05:32:56 +01:00
|
|
|
m_page_table_heap.Initialize(std::addressof(m_dynamic_page_manager), 0, GetPointer<KPageTableManager::RefCount>(m_resource_address));
|
|
|
|
m_memory_block_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
|
|
|
m_block_info_heap.Initialize(std::addressof(m_dynamic_page_manager), 0);
|
|
|
|
|
|
|
|
/* Initialize managers. */
|
|
|
|
m_page_table_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_page_table_heap));
|
|
|
|
m_memory_block_slab_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_memory_block_heap));
|
|
|
|
m_block_info_manager.Initialize(std::addressof(m_dynamic_page_manager), std::addressof(m_block_info_heap));
|
|
|
|
|
|
|
|
/* Set our managers. */
|
|
|
|
this->SetManagers(m_memory_block_slab_manager, m_block_info_manager, m_page_table_manager);
|
|
|
|
|
|
|
|
/* Commit the memory reservation. */
|
|
|
|
memory_reservation.Commit();
|
|
|
|
|
|
|
|
/* Open reference to our resource limit. */
|
|
|
|
m_resource_limit->Open();
|
|
|
|
|
|
|
|
/* Set ourselves as initialized. */
|
|
|
|
m_is_initialized = true;
|
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KSecureSystemResource::Finalize() {
|
|
|
|
/* Check that we have no outstanding allocations. */
|
|
|
|
MESOSPHERE_ABORT_UNLESS(m_memory_block_slab_manager.GetUsed() == 0);
|
|
|
|
MESOSPHERE_ABORT_UNLESS(m_block_info_manager.GetUsed() == 0);
|
|
|
|
MESOSPHERE_ABORT_UNLESS(m_page_table_manager.GetUsed() == 0);
|
|
|
|
|
|
|
|
/* Free our secure memory. */
|
|
|
|
KSystemControl::FreeSecureMemory(m_resource_address, m_resource_size, m_resource_pool);
|
|
|
|
|
|
|
|
/* Release the memory reservation. */
|
|
|
|
m_resource_limit->Release(ams::svc::LimitableResource_PhysicalMemoryMax, this->CalculateRequiredSecureMemorySize());
|
|
|
|
|
|
|
|
/* Close reference to our resource limit. */
|
|
|
|
m_resource_limit->Close();
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t KSecureSystemResource::CalculateRequiredSecureMemorySize(size_t size, KMemoryManager::Pool pool) {
|
|
|
|
return KSystemControl::CalculateRequiredSecureMemorySize(size, pool);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|