mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-11-16 17:11:18 +01:00
NOTE: This work is not yet fully complete; kernel is done, but it was taking an exceedingly long time to get through libstratosphere. Thus, I've temporarily added -Wno-error=unused-result for libstratosphere/stratosphere. All warnings should be fixed to do the same thing Nintendo does as relevant, but this is taking a phenomenally long time and is not actually the most important work to do, so it can be put off for some time to prioritize other tasks for 21.0.0 support.
96 lines
4.3 KiB
C++
96 lines
4.3 KiB
C++
/*
|
|
* 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. */
|
|
R_TRY(m_dynamic_page_manager.Initialize(m_resource_address + rc_size, m_resource_size - rc_size, PageSize));
|
|
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. */
|
|
if (m_resource_limit != nullptr) {
|
|
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);
|
|
|
|
/* Clean up our resource usage. */
|
|
if (m_resource_limit != nullptr) {
|
|
/* 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);
|
|
}
|
|
|
|
}
|