mirror of
				https://github.com/Atmosphere-NX/Atmosphere-libs.git
				synced 2025-11-04 05:11:18 +01:00 
			
		
		
		
	kern: update Initialize0 for new arguments/randomization semantics
This commit is contained in:
		
							parent
							
								
									f103b6876b
								
							
						
					
					
						commit
						3e328eae72
					
				@ -293,7 +293,7 @@ namespace ams::kern::arch::arm64::init {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                /* Swap the mappings. */
 | 
			
		||||
                const u64 attr_preserve_mask  = (negative_block_size_for_mask | 0xFFFF000000000000ul) ^ ((1ul << 48) - 1);
 | 
			
		||||
                const u64 attr_preserve_mask  = (block_size - 1) | 0xFFFF000000000000ul;
 | 
			
		||||
                const size_t shift_for_contig = contig ? 4 : 0;
 | 
			
		||||
                size_t advanced_size = 0;
 | 
			
		||||
                const u64 src_attr_val = src_saved.GetRawAttributesUnsafeForSwap() & attr_preserve_mask;
 | 
			
		||||
@ -726,8 +726,8 @@ namespace ams::kern::arch::arm64::init {
 | 
			
		||||
                m_state.end_address  = address;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) {
 | 
			
		||||
                m_state = *reinterpret_cast<State *>(state_val);
 | 
			
		||||
            ALWAYS_INLINE void InitializeFromState(const State *state) {
 | 
			
		||||
                m_state = *state;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ALWAYS_INLINE void GetFinalState(State *out) {
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,12 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
#include <mesosphere/kern_common.hpp>
 | 
			
		||||
 | 
			
		||||
namespace ams::kern {
 | 
			
		||||
 | 
			
		||||
    struct InitialProcessBinaryLayout;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace ams::kern::board::nintendo::nx {
 | 
			
		||||
 | 
			
		||||
    class KSystemControl {
 | 
			
		||||
@ -25,7 +31,7 @@ namespace ams::kern::board::nintendo::nx {
 | 
			
		||||
                    /* Initialization. */
 | 
			
		||||
                    static size_t GetIntendedMemorySize();
 | 
			
		||||
                    static KPhysicalAddress GetKernelPhysicalBaseAddress(uintptr_t base_address);
 | 
			
		||||
                    static KPhysicalAddress GetInitialProcessBinaryPhysicalAddress();
 | 
			
		||||
                    static void GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out);
 | 
			
		||||
                    static bool ShouldIncreaseThreadResourceLimit();
 | 
			
		||||
                    static void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
 | 
			
		||||
                    static size_t GetApplicationPoolSize();
 | 
			
		||||
 | 
			
		||||
@ -29,14 +29,19 @@ namespace ams::kern {
 | 
			
		||||
        u32 reserved;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    NOINLINE size_t CopyInitialProcessBinaryToKernelMemory();
 | 
			
		||||
    NOINLINE void CreateAndRunInitialProcesses();
 | 
			
		||||
    struct InitialProcessBinaryLayout {
 | 
			
		||||
        uintptr_t address;
 | 
			
		||||
        uintptr_t _08;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    KPhysicalAddress GetInitialProcessBinaryPhysicalAddress();
 | 
			
		||||
    void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr);
 | 
			
		||||
 | 
			
		||||
    u64 GetInitialProcessIdMin();
 | 
			
		||||
    u64 GetInitialProcessIdMax();
 | 
			
		||||
    KVirtualAddress GetInitialProcessBinaryAddress();
 | 
			
		||||
    size_t GetInitialProcessesSecureMemorySize();
 | 
			
		||||
 | 
			
		||||
    void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end);
 | 
			
		||||
    NOINLINE size_t CopyInitialProcessBinaryToKernelMemory();
 | 
			
		||||
    NOINLINE void CreateAndRunInitialProcesses();
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -237,12 +237,6 @@ namespace ams::kern {
 | 
			
		||||
        public:
 | 
			
		||||
            NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr = 0, u32 type_id = 0);
 | 
			
		||||
            NOINLINE bool Insert(uintptr_t address, size_t size, u32 type_id, u32 new_attr = 0, u32 old_attr = 0);
 | 
			
		||||
 | 
			
		||||
            NOINLINE KVirtualAddress GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id);
 | 
			
		||||
 | 
			
		||||
            ALWAYS_INLINE KVirtualAddress GetRandomAlignedRegionWithGuard(size_t size, size_t alignment, u32 type_id, size_t guard_size) {
 | 
			
		||||
                return this->GetRandomAlignedRegion(size + 2 * guard_size, alignment, type_id) + guard_size;
 | 
			
		||||
            }
 | 
			
		||||
        public:
 | 
			
		||||
            /* Iterator accessors. */
 | 
			
		||||
            iterator begin() {
 | 
			
		||||
 | 
			
		||||
@ -346,8 +346,11 @@ namespace ams::kern::board::nintendo::nx {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPhysicalAddress KSystemControl::Init::GetInitialProcessBinaryPhysicalAddress() {
 | 
			
		||||
        return GetKernelPhysicalBaseAddress(DramPhysicalAddress) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax;
 | 
			
		||||
    void KSystemControl::Init::GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out) {
 | 
			
		||||
        *out = {
 | 
			
		||||
            .address = GetInteger(GetKernelPhysicalBaseAddress(DramPhysicalAddress)) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax,
 | 
			
		||||
            ._08     = 0,
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
 | 
			
		||||
 | 
			
		||||
@ -25,18 +25,18 @@ namespace ams::kern {
 | 
			
		||||
            s32 priority;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        constinit KPhysicalAddress g_initial_process_binary_phys_addr = Null<KPhysicalAddress>;
 | 
			
		||||
        constinit KVirtualAddress g_initial_process_binary_address = Null<KVirtualAddress>;
 | 
			
		||||
        constinit InitialProcessBinaryHeader g_initial_process_binary_header = {};
 | 
			
		||||
        constinit size_t g_initial_process_secure_memory_size = 0;
 | 
			
		||||
        constinit u64 g_initial_process_id_min = std::numeric_limits<u64>::max();
 | 
			
		||||
        constinit u64 g_initial_process_id_max = std::numeric_limits<u64>::min();
 | 
			
		||||
 | 
			
		||||
        void LoadInitialProcessBinaryHeader(KVirtualAddress virt_addr = Null<KVirtualAddress>) {
 | 
			
		||||
        void LoadInitialProcessBinaryHeader() {
 | 
			
		||||
            if (g_initial_process_binary_header.magic != InitialProcessBinaryMagic) {
 | 
			
		||||
                /* Get the virtual address, if it's not overridden. */
 | 
			
		||||
                if (virt_addr == Null<KVirtualAddress>) {
 | 
			
		||||
                    virt_addr = GetInitialProcessBinaryAddress();
 | 
			
		||||
                }
 | 
			
		||||
                /* Get the virtual address. */
 | 
			
		||||
                MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null<KPhysicalAddress>);
 | 
			
		||||
                const KVirtualAddress virt_addr = KMemoryLayout::GetLinearVirtualAddress(g_initial_process_binary_phys_addr);
 | 
			
		||||
 | 
			
		||||
                /* Copy and validate the header. */
 | 
			
		||||
                g_initial_process_binary_header = *GetPointer<InitialProcessBinaryHeader>(virt_addr);
 | 
			
		||||
@ -273,10 +273,18 @@ namespace ams::kern {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ALWAYS_INLINE KVirtualAddress GetInitialProcessBinaryAddress(KVirtualAddress pool_end) {
 | 
			
		||||
            return pool_end - InitialProcessBinarySizeMax;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr) {
 | 
			
		||||
        MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr == Null<KPhysicalAddress>);
 | 
			
		||||
 | 
			
		||||
        g_initial_process_binary_phys_addr = phys_addr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KPhysicalAddress GetInitialProcessBinaryPhysicalAddress() {
 | 
			
		||||
        MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null<KPhysicalAddress>);
 | 
			
		||||
 | 
			
		||||
        return g_initial_process_binary_phys_addr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    u64 GetInitialProcessIdMin() {
 | 
			
		||||
@ -287,15 +295,6 @@ namespace ams::kern {
 | 
			
		||||
        return g_initial_process_id_max;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KVirtualAddress GetInitialProcessBinaryAddress() {
 | 
			
		||||
        /* Get, validate the pool region. */
 | 
			
		||||
        const auto *pool_region = KMemoryLayout::GetVirtualMemoryRegionTree().FindLastDerived(KMemoryRegionType_VirtualDramUserPool);
 | 
			
		||||
        MESOSPHERE_INIT_ABORT_UNLESS(pool_region != nullptr);
 | 
			
		||||
        MESOSPHERE_INIT_ABORT_UNLESS(pool_region->GetEndAddress() != 0);
 | 
			
		||||
        MESOSPHERE_ABORT_UNLESS(pool_region->GetSize() >= InitialProcessBinarySizeMax);
 | 
			
		||||
        return GetInitialProcessBinaryAddress(pool_region->GetEndAddress());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    size_t GetInitialProcessesSecureMemorySize() {
 | 
			
		||||
        LoadInitialProcessBinaryHeader();
 | 
			
		||||
 | 
			
		||||
@ -321,10 +320,6 @@ namespace ams::kern {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end) {
 | 
			
		||||
        LoadInitialProcessBinaryHeader(GetInitialProcessBinaryAddress(KMemoryLayout::GetLinearVirtualAddress(pool_end)));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void CreateAndRunInitialProcesses() {
 | 
			
		||||
        /* Allocate space for the processes. */
 | 
			
		||||
        InitialProcessInfo *infos = static_cast<InitialProcessInfo *>(__builtin_alloca(sizeof(InitialProcessInfo) * g_initial_process_binary_header.num_processes));
 | 
			
		||||
 | 
			
		||||
@ -190,12 +190,6 @@ namespace ams::kern {
 | 
			
		||||
                static_assert(KMemoryManager::Pool_Unsafe == KMemoryManager::Pool_Application);
 | 
			
		||||
                static_assert(KMemoryManager::Pool_Secure == KMemoryManager::Pool_System);
 | 
			
		||||
 | 
			
		||||
                /* NOTE: Beginning with 12.0.0 (and always, in mesosphere), the initial process binary is at the end of the pool region. */
 | 
			
		||||
                /*       However, this is problematic for < 5.0.0, because we require the initial process binary to be parsed in order   */
 | 
			
		||||
                /*       to determine the pool sizes. Hence, we will force an initial binary load with the known pool end directly, so   */
 | 
			
		||||
                /*       that we retain compatibility with lower firmware versions. */
 | 
			
		||||
                LoadInitialProcessBinaryHeaderDeprecated(pool_end);
 | 
			
		||||
 | 
			
		||||
                /* Get Secure pool size. */
 | 
			
		||||
                const size_t secure_pool_size = [] ALWAYS_INLINE_LAMBDA (auto target_firmware) -> size_t {
 | 
			
		||||
                    constexpr size_t LegacySecureKernelSize = 8_MB;          /* KPageBuffer pages, other small kernel allocations. */
 | 
			
		||||
 | 
			
		||||
@ -111,43 +111,6 @@ namespace ams::kern {
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    KVirtualAddress KMemoryRegionTree::GetRandomAlignedRegion(size_t size, size_t alignment, u32 type_id) {
 | 
			
		||||
        /* We want to find the total extents of the type id. */
 | 
			
		||||
        const auto extents = this->GetDerivedRegionExtents(type_id);
 | 
			
		||||
 | 
			
		||||
        /* Ensure that our alignment is correct. */
 | 
			
		||||
        MESOSPHERE_INIT_ABORT_UNLESS(util::IsAligned(extents.GetAddress(), alignment));
 | 
			
		||||
 | 
			
		||||
        const uintptr_t first_address = extents.GetAddress();
 | 
			
		||||
        const uintptr_t last_address  = extents.GetLastAddress();
 | 
			
		||||
 | 
			
		||||
        const uintptr_t first_index = first_address / alignment;
 | 
			
		||||
        const uintptr_t last_index  = last_address / alignment;
 | 
			
		||||
 | 
			
		||||
        while (true) {
 | 
			
		||||
            const uintptr_t candidate = KSystemControl::Init::GenerateRandomRange(first_index, last_index) * alignment;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that the candidate doesn't overflow with the size. */
 | 
			
		||||
            if (!(candidate < candidate + size)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const uintptr_t candidate_last = candidate + size - 1;
 | 
			
		||||
 | 
			
		||||
            /* Ensure that the candidate fits within the region. */
 | 
			
		||||
            if (candidate_last > last_address) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            /* Locate the candidate region, and ensure it fits and has the correct type id. */
 | 
			
		||||
            if (const auto &candidate_region = *this->Find(candidate); !(candidate_last <= candidate_region.GetLastAddress() && candidate_region.GetType() == type_id)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return candidate;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void KMemoryLayout::InitializeLinearMemoryRegionTrees() {
 | 
			
		||||
        /* Initialize linear trees. */
 | 
			
		||||
        for (auto ®ion : GetPhysicalMemoryRegionTree()) {
 | 
			
		||||
 | 
			
		||||
@ -107,7 +107,7 @@ namespace ams::kern {
 | 
			
		||||
 | 
			
		||||
        /* Free each region to its corresponding heap. */
 | 
			
		||||
        size_t reserved_sizes[MaxManagerCount] = {};
 | 
			
		||||
        const KPhysicalAddress ini_start = KMemoryLayout::GetLinearPhysicalAddress(GetInitialProcessBinaryAddress());
 | 
			
		||||
        const KPhysicalAddress ini_start = GetInitialProcessBinaryPhysicalAddress();
 | 
			
		||||
        const KPhysicalAddress ini_end   = ini_start + InitialProcessBinarySizeMax;
 | 
			
		||||
        const KPhysicalAddress ini_last  = ini_end - 1;
 | 
			
		||||
        for (const auto &it : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user