mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 12:21:18 +00:00
kern: fix initial process binary load on 2.0.0-4.1.0 (closes #1460)
This commit is contained in:
parent
ed80d6ec8c
commit
19be54ff95
6 changed files with 40 additions and 12 deletions
|
@ -37,4 +37,6 @@ namespace ams::kern {
|
|||
KVirtualAddress GetInitialProcessBinaryAddress();
|
||||
size_t GetInitialProcessesSecureMemorySize();
|
||||
|
||||
void LoadInitialProcessBinaryHeaderDeprecated(KPhysicalAddress pool_end);
|
||||
|
||||
}
|
||||
|
|
|
@ -175,7 +175,14 @@ namespace ams::kern {
|
|||
return std::make_tuple(total_size, kernel_size);
|
||||
}
|
||||
|
||||
static void InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start);
|
||||
static void InitializeLinearMemoryAddresses(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start) {
|
||||
/* Set static differences. */
|
||||
s_linear_phys_to_virt_diff = GetInteger(linear_virtual_start) - GetInteger(aligned_linear_phys_start);
|
||||
s_linear_virt_to_phys_diff = GetInteger(aligned_linear_phys_start) - GetInteger(linear_virtual_start);
|
||||
}
|
||||
|
||||
static void InitializeLinearMemoryRegionTrees();
|
||||
|
||||
static size_t GetResourceRegionSizeForInit();
|
||||
|
||||
static NOINLINE auto GetKernelRegionExtents() { return GetVirtualMemoryRegionTree().GetDerivedRegionExtents(KMemoryRegionType_Kernel); }
|
||||
|
|
|
@ -31,10 +31,12 @@ namespace ams::kern {
|
|||
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() {
|
||||
void LoadInitialProcessBinaryHeader(KVirtualAddress virt_addr = Null<KVirtualAddress>) {
|
||||
if (g_initial_process_binary_header.magic != InitialProcessBinaryMagic) {
|
||||
/* Get the virtual address for the image. */
|
||||
const KVirtualAddress virt_addr = GetInitialProcessBinaryAddress();
|
||||
/* Get the virtual address, if it's not overridden. */
|
||||
if (virt_addr == Null<KVirtualAddress>) {
|
||||
virt_addr = GetInitialProcessBinaryAddress();
|
||||
}
|
||||
|
||||
/* Copy and validate the header. */
|
||||
g_initial_process_binary_header = *GetPointer<InitialProcessBinaryHeader>(virt_addr);
|
||||
|
@ -54,12 +56,16 @@ namespace ams::kern {
|
|||
|
||||
/* Attach to the current KIP. */
|
||||
KInitialProcessReader reader;
|
||||
MESOSPHERE_ABORT_UNLESS(reader.Attach(current) != Null<KVirtualAddress>);
|
||||
KVirtualAddress data = reader.Attach(current);
|
||||
MESOSPHERE_ABORT_UNLESS(data != Null<KVirtualAddress>);
|
||||
|
||||
/* If the process uses secure memory, account for that. */
|
||||
if (reader.UsesSecureMemory()) {
|
||||
g_initial_process_secure_memory_size += reader.GetSize() + util::AlignUp(reader.GetStackSize(), PageSize);
|
||||
}
|
||||
|
||||
/* Advance to the next KIP. */
|
||||
current = data + reader.GetBinarySize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,6 +273,10 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
ALWAYS_INLINE KVirtualAddress GetInitialProcessBinaryAddress(KVirtualAddress pool_end) {
|
||||
return pool_end - InitialProcessBinarySizeMax;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u64 GetInitialProcessIdMin() {
|
||||
|
@ -283,7 +293,7 @@ namespace ams::kern {
|
|||
MESOSPHERE_INIT_ABORT_UNLESS(pool_region != nullptr);
|
||||
MESOSPHERE_INIT_ABORT_UNLESS(pool_region->GetEndAddress() != 0);
|
||||
MESOSPHERE_ABORT_UNLESS(pool_region->GetSize() >= InitialProcessBinarySizeMax);
|
||||
return pool_region->GetEndAddress() - InitialProcessBinarySizeMax;
|
||||
return GetInitialProcessBinaryAddress(pool_region->GetEndAddress());
|
||||
}
|
||||
|
||||
size_t GetInitialProcessesSecureMemorySize() {
|
||||
|
@ -311,6 +321,10 @@ 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));
|
||||
|
|
|
@ -185,6 +185,12 @@ 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. */
|
||||
|
|
|
@ -148,11 +148,7 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
void KMemoryLayout::InitializeLinearMemoryRegionTrees(KPhysicalAddress aligned_linear_phys_start, KVirtualAddress linear_virtual_start) {
|
||||
/* Set static differences. */
|
||||
s_linear_phys_to_virt_diff = GetInteger(linear_virtual_start) - GetInteger(aligned_linear_phys_start);
|
||||
s_linear_virt_to_phys_diff = GetInteger(aligned_linear_phys_start) - GetInteger(linear_virtual_start);
|
||||
|
||||
void KMemoryLayout::InitializeLinearMemoryRegionTrees() {
|
||||
/* Initialize linear trees. */
|
||||
for (auto ®ion : GetPhysicalMemoryRegionTree()) {
|
||||
if (region.HasTypeAttribute(KMemoryRegionAttr_LinearMapped)) {
|
||||
|
|
|
@ -467,11 +467,14 @@ namespace ams::kern::init {
|
|||
}
|
||||
}
|
||||
|
||||
/* Set the linear memory offsets, to enable conversion between physical and virtual addresses. */
|
||||
KMemoryLayout::InitializeLinearMemoryAddresses(aligned_linear_phys_start, linear_region_start);
|
||||
|
||||
/* Setup all other memory regions needed to arrange the pool partitions. */
|
||||
SetupPoolPartitionMemoryRegions();
|
||||
|
||||
/* Cache all linear regions in their own trees for faster access, later. */
|
||||
KMemoryLayout::InitializeLinearMemoryRegionTrees(aligned_linear_phys_start, linear_region_start);
|
||||
KMemoryLayout::InitializeLinearMemoryRegionTrees();
|
||||
|
||||
/* Turn on all other cores. */
|
||||
TurnOnAllCores(GetInteger(init_pt.GetPhysicalAddress(reinterpret_cast<uintptr_t>(::ams::kern::init::StartOtherCore))));
|
||||
|
|
Loading…
Reference in a new issue