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. */
 | 
					                /* 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;
 | 
					                const size_t shift_for_contig = contig ? 4 : 0;
 | 
				
			||||||
                size_t advanced_size = 0;
 | 
					                size_t advanced_size = 0;
 | 
				
			||||||
                const u64 src_attr_val = src_saved.GetRawAttributesUnsafeForSwap() & attr_preserve_mask;
 | 
					                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;
 | 
					                m_state.end_address  = address;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ALWAYS_INLINE void InitializeFromState(uintptr_t state_val) {
 | 
					            ALWAYS_INLINE void InitializeFromState(const State *state) {
 | 
				
			||||||
                m_state = *reinterpret_cast<State *>(state_val);
 | 
					                m_state = *state;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ALWAYS_INLINE void GetFinalState(State *out) {
 | 
					            ALWAYS_INLINE void GetFinalState(State *out) {
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,12 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <mesosphere/kern_common.hpp>
 | 
					#include <mesosphere/kern_common.hpp>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace ams::kern {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    struct InitialProcessBinaryLayout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace ams::kern::board::nintendo::nx {
 | 
					namespace ams::kern::board::nintendo::nx {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class KSystemControl {
 | 
					    class KSystemControl {
 | 
				
			||||||
@ -25,7 +31,7 @@ namespace ams::kern::board::nintendo::nx {
 | 
				
			|||||||
                    /* Initialization. */
 | 
					                    /* Initialization. */
 | 
				
			||||||
                    static size_t GetIntendedMemorySize();
 | 
					                    static size_t GetIntendedMemorySize();
 | 
				
			||||||
                    static KPhysicalAddress GetKernelPhysicalBaseAddress(uintptr_t base_address);
 | 
					                    static KPhysicalAddress GetKernelPhysicalBaseAddress(uintptr_t base_address);
 | 
				
			||||||
                    static KPhysicalAddress GetInitialProcessBinaryPhysicalAddress();
 | 
					                    static void GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out);
 | 
				
			||||||
                    static bool ShouldIncreaseThreadResourceLimit();
 | 
					                    static bool ShouldIncreaseThreadResourceLimit();
 | 
				
			||||||
                    static void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
 | 
					                    static void CpuOn(u64 core_id, uintptr_t entrypoint, uintptr_t arg);
 | 
				
			||||||
                    static size_t GetApplicationPoolSize();
 | 
					                    static size_t GetApplicationPoolSize();
 | 
				
			||||||
 | 
				
			|||||||
@ -29,14 +29,19 @@ namespace ams::kern {
 | 
				
			|||||||
        u32 reserved;
 | 
					        u32 reserved;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NOINLINE size_t CopyInitialProcessBinaryToKernelMemory();
 | 
					    struct InitialProcessBinaryLayout {
 | 
				
			||||||
    NOINLINE void CreateAndRunInitialProcesses();
 | 
					        uintptr_t address;
 | 
				
			||||||
 | 
					        uintptr_t _08;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    KPhysicalAddress GetInitialProcessBinaryPhysicalAddress();
 | 
				
			||||||
 | 
					    void SetInitialProcessBinaryPhysicalAddress(KPhysicalAddress phys_addr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u64 GetInitialProcessIdMin();
 | 
					    u64 GetInitialProcessIdMin();
 | 
				
			||||||
    u64 GetInitialProcessIdMax();
 | 
					    u64 GetInitialProcessIdMax();
 | 
				
			||||||
    KVirtualAddress GetInitialProcessBinaryAddress();
 | 
					 | 
				
			||||||
    size_t GetInitialProcessesSecureMemorySize();
 | 
					    size_t GetInitialProcessesSecureMemorySize();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end);
 | 
					    NOINLINE size_t CopyInitialProcessBinaryToKernelMemory();
 | 
				
			||||||
 | 
					    NOINLINE void CreateAndRunInitialProcesses();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -237,12 +237,6 @@ namespace ams::kern {
 | 
				
			|||||||
        public:
 | 
					        public:
 | 
				
			||||||
            NOINLINE void InsertDirectly(uintptr_t address, uintptr_t last_address, u32 attr = 0, u32 type_id = 0);
 | 
					            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 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:
 | 
					        public:
 | 
				
			||||||
            /* Iterator accessors. */
 | 
					            /* Iterator accessors. */
 | 
				
			||||||
            iterator begin() {
 | 
					            iterator begin() {
 | 
				
			||||||
 | 
				
			|||||||
@ -346,8 +346,11 @@ namespace ams::kern::board::nintendo::nx {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    KPhysicalAddress KSystemControl::Init::GetInitialProcessBinaryPhysicalAddress() {
 | 
					    void KSystemControl::Init::GetInitialProcessBinaryLayout(InitialProcessBinaryLayout *out) {
 | 
				
			||||||
        return GetKernelPhysicalBaseAddress(DramPhysicalAddress) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax;
 | 
					        *out = {
 | 
				
			||||||
 | 
					            .address = GetInteger(GetKernelPhysicalBaseAddress(DramPhysicalAddress)) + GetIntendedMemorySize() - KTraceBufferSize - InitialProcessBinarySizeMax,
 | 
				
			||||||
 | 
					            ._08     = 0,
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
 | 
					    bool KSystemControl::Init::ShouldIncreaseThreadResourceLimit() {
 | 
				
			||||||
 | 
				
			|||||||
@ -25,18 +25,18 @@ namespace ams::kern {
 | 
				
			|||||||
            s32 priority;
 | 
					            s32 priority;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        constinit KPhysicalAddress g_initial_process_binary_phys_addr = Null<KPhysicalAddress>;
 | 
				
			||||||
        constinit KVirtualAddress g_initial_process_binary_address = Null<KVirtualAddress>;
 | 
					        constinit KVirtualAddress g_initial_process_binary_address = Null<KVirtualAddress>;
 | 
				
			||||||
        constinit InitialProcessBinaryHeader g_initial_process_binary_header = {};
 | 
					        constinit InitialProcessBinaryHeader g_initial_process_binary_header = {};
 | 
				
			||||||
        constinit size_t g_initial_process_secure_memory_size = 0;
 | 
					        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_min = std::numeric_limits<u64>::max();
 | 
				
			||||||
        constinit u64 g_initial_process_id_max = std::numeric_limits<u64>::min();
 | 
					        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) {
 | 
					            if (g_initial_process_binary_header.magic != InitialProcessBinaryMagic) {
 | 
				
			||||||
                /* Get the virtual address, if it's not overridden. */
 | 
					                /* Get the virtual address. */
 | 
				
			||||||
                if (virt_addr == Null<KVirtualAddress>) {
 | 
					                MESOSPHERE_INIT_ABORT_UNLESS(g_initial_process_binary_phys_addr != Null<KPhysicalAddress>);
 | 
				
			||||||
                    virt_addr = GetInitialProcessBinaryAddress();
 | 
					                const KVirtualAddress virt_addr = KMemoryLayout::GetLinearVirtualAddress(g_initial_process_binary_phys_addr);
 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                /* Copy and validate the header. */
 | 
					                /* Copy and validate the header. */
 | 
				
			||||||
                g_initial_process_binary_header = *GetPointer<InitialProcessBinaryHeader>(virt_addr);
 | 
					                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() {
 | 
					    u64 GetInitialProcessIdMin() {
 | 
				
			||||||
@ -287,15 +295,6 @@ namespace ams::kern {
 | 
				
			|||||||
        return g_initial_process_id_max;
 | 
					        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() {
 | 
					    size_t GetInitialProcessesSecureMemorySize() {
 | 
				
			||||||
        LoadInitialProcessBinaryHeader();
 | 
					        LoadInitialProcessBinaryHeader();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -321,10 +320,6 @@ namespace ams::kern {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end) {
 | 
					 | 
				
			||||||
        LoadInitialProcessBinaryHeader(GetInitialProcessBinaryAddress(KMemoryLayout::GetLinearVirtualAddress(pool_end)));
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    void CreateAndRunInitialProcesses() {
 | 
					    void CreateAndRunInitialProcesses() {
 | 
				
			||||||
        /* Allocate space for the processes. */
 | 
					        /* Allocate space for the processes. */
 | 
				
			||||||
        InitialProcessInfo *infos = static_cast<InitialProcessInfo *>(__builtin_alloca(sizeof(InitialProcessInfo) * g_initial_process_binary_header.num_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_Unsafe == KMemoryManager::Pool_Application);
 | 
				
			||||||
                static_assert(KMemoryManager::Pool_Secure == KMemoryManager::Pool_System);
 | 
					                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. */
 | 
					                /* Get Secure pool size. */
 | 
				
			||||||
                const size_t secure_pool_size = [] ALWAYS_INLINE_LAMBDA (auto target_firmware) -> size_t {
 | 
					                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. */
 | 
					                    constexpr size_t LegacySecureKernelSize = 8_MB;          /* KPageBuffer pages, other small kernel allocations. */
 | 
				
			||||||
 | 
				
			|||||||
@ -111,43 +111,6 @@ namespace ams::kern {
 | 
				
			|||||||
        return true;
 | 
					        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() {
 | 
					    void KMemoryLayout::InitializeLinearMemoryRegionTrees() {
 | 
				
			||||||
        /* Initialize linear trees. */
 | 
					        /* Initialize linear trees. */
 | 
				
			||||||
        for (auto ®ion : GetPhysicalMemoryRegionTree()) {
 | 
					        for (auto ®ion : GetPhysicalMemoryRegionTree()) {
 | 
				
			||||||
 | 
				
			|||||||
@ -107,7 +107,7 @@ namespace ams::kern {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* Free each region to its corresponding heap. */
 | 
					        /* Free each region to its corresponding heap. */
 | 
				
			||||||
        size_t reserved_sizes[MaxManagerCount] = {};
 | 
					        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_end   = ini_start + InitialProcessBinarySizeMax;
 | 
				
			||||||
        const KPhysicalAddress ini_last  = ini_end - 1;
 | 
					        const KPhysicalAddress ini_last  = ini_end - 1;
 | 
				
			||||||
        for (const auto &it : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
 | 
					        for (const auto &it : KMemoryLayout::GetPhysicalMemoryRegionTree()) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user