diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index bb035805f..a8f82ccc4 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -147,6 +147,8 @@ namespace ams::kern { constexpr KProcessAddress GetEntryPoint() const { return this->code_address; } + constexpr u64 GetRandomEntropy(size_t i) const { return this->entropy[i]; } + constexpr bool IsSuspended() const { return this->is_suspended; } diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp index f79cdf09f..b0122c095 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp @@ -528,7 +528,42 @@ namespace ams::kern::board::nintendo::nx { } void KDevicePageTable::Finalize() { - MESOSPHERE_UNIMPLEMENTED(); + /* Get the page table manager. */ + auto &ptm = Kernel::GetPageTableManager(); + + /* Detach from all devices. */ + { + KScopedLightLock lk(g_lock); + for (size_t i = 0; i < ams::svc::DeviceName_Count; ++i) { + const auto device_name = static_cast(i); + if ((this->attached_device & (1ul << device_name)) != 0) { + WriteMcRegister(GetDeviceAsidRegisterOffset(device_name), IsHsSupported(device_name) ? this->hs_detached_value : this->detached_value); + SmmuSynchronizationBarrier(); + } + } + } + + /* Forcibly unmap all pages. */ + this->UnmapImpl(0, (1ul << DeviceVirtualAddressBits), true); + + /* Release all asids. */ + for (size_t i = 0; i < TableCount; ++i) { + if (this->table_asids[i] != g_reserved_asid) { + /* Set the table to the reserved table. */ + SetTable(this->table_asids[i], g_reserved_table_phys_addr); + + /* Close the table. */ + const KVirtualAddress table_vaddr = this->tables[i]; + MESOSPHERE_ASSERT(ptm.GetRefCount(table_vaddr) == 1); + MESOSPHERE_ABORT_UNLESS(ptm.Close(table_vaddr, 1)); + + /* Free the table. */ + ptm.Free(table_vaddr); + + /* Release the asid. */ + g_asid_manager.Release(this->table_asids[i]); + } + } } Result KDevicePageTable::Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size) { diff --git a/libraries/libmesosphere/source/svc/kern_svc_info.cpp b/libraries/libmesosphere/source/svc/kern_svc_info.cpp index 4604849b3..8254a0dad 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_info.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_info.cpp @@ -132,6 +132,18 @@ namespace ams::kern::svc { } } break; + case ams::svc::InfoType_RandomEntropy: + { + /* Verify the input handle is invalid. */ + R_UNLESS(handle == ams::svc::InvalidHandle, svc::ResultInvalidHandle()); + + /* Verify the requested entropy is valid. */ + R_UNLESS(info_subtype < 4, svc::ResultInvalidCombination()); + + /* Get the entropy. */ + *out = GetCurrentProcess().GetRandomEntropy(info_subtype); + } + break; default: return svc::ResultInvalidEnumValue(); }