mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-09 22:56:35 +00:00
kern: skeleton initial process loading
This commit is contained in:
parent
30d6b359f9
commit
cbc73f4407
7 changed files with 465 additions and 1 deletions
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_initial_process_reader.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
@ -29,6 +30,7 @@ namespace ams::kern {
|
|||
};
|
||||
|
||||
NOINLINE void CopyInitialProcessBinaryToKernelMemory();
|
||||
NOINLINE void CreateAndRunInitialProcesses();
|
||||
|
||||
u64 GetInitialProcessIdMin();
|
||||
u64 GetInitialProcessIdMax();
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
|
||||
|
||||
struct KAddressSpaceInfo {
|
||||
public:
|
||||
enum Type {
|
||||
Type_32Bit = 0,
|
||||
Type_Small64Bit = 1,
|
||||
Type_Large64Bit = 2,
|
||||
Type_Heap = 3,
|
||||
Type_Stack = 4,
|
||||
Type_Alias = 5,
|
||||
|
||||
Type_Count,
|
||||
};
|
||||
private:
|
||||
size_t bit_width;
|
||||
size_t address;
|
||||
size_t size;
|
||||
Type type;
|
||||
public:
|
||||
static uintptr_t GetAddressSpaceStart(size_t width, Type type);
|
||||
static size_t GetAddressSpaceSize(size_t width, Type type);
|
||||
|
||||
constexpr KAddressSpaceInfo(size_t bw, size_t a, size_t s, Type t) : bit_width(bw), address(a), size(s), type(t) { /* ... */ }
|
||||
|
||||
constexpr size_t GetWidth() const { return this->bit_width; }
|
||||
constexpr size_t GetAddress() const { return this->address; }
|
||||
constexpr size_t GetSize() const { return this->size; }
|
||||
constexpr Type GetType() const { return this->type; }
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include <mesosphere/kern_common.hpp>
|
||||
#include <mesosphere/kern_k_address_space_info.hpp>
|
||||
|
||||
namespace ams::kern {
|
||||
|
||||
class KInitialProcessHeader {
|
||||
private:
|
||||
static constexpr u32 Magic = util::FourCC<'K','I','P','1'>::Code;
|
||||
private:
|
||||
u32 magic;
|
||||
u8 name[12];
|
||||
u64 program_id;
|
||||
u32 version;
|
||||
u8 priority;
|
||||
u8 ideal_core_id;
|
||||
u8 _1E;
|
||||
u8 flags;
|
||||
u32 rx_address;
|
||||
u32 rx_size;
|
||||
u32 rx_compressed_size;
|
||||
u32 affinity_mask;
|
||||
u32 ro_address;
|
||||
u32 ro_size;
|
||||
u32 ro_compressed_size;
|
||||
u32 stack_size;
|
||||
u32 rw_address;
|
||||
u32 rw_size;
|
||||
u32 rw_compressed_size;
|
||||
u32 _4C;
|
||||
u32 bss_address;
|
||||
u32 bss_size;
|
||||
u32 pad[(0x80 - 0x58) / sizeof(u32)];
|
||||
u32 capabilities[0x80 / sizeof(u32)];
|
||||
public:
|
||||
constexpr bool IsValid() const { return this->magic == Magic; }
|
||||
|
||||
constexpr void GetName(char *dst, size_t size) const {
|
||||
std::memset(dst, 0, size);
|
||||
std::memcpy(dst, this->name, std::min(sizeof(this->name), size));
|
||||
}
|
||||
|
||||
constexpr const u32 *GetCapabilities() const { return this->capabilities; }
|
||||
constexpr size_t GetNumCapabilities() const { return util::size(this->capabilities); }
|
||||
|
||||
constexpr u64 GetProgramId() const { return this->program_id; }
|
||||
constexpr u32 GetVersion() const { return this->version; }
|
||||
constexpr u8 GetPriority() const { return this->priority; }
|
||||
constexpr u8 GetIdealCore() const { return this->ideal_core_id; }
|
||||
|
||||
constexpr bool IsRxCompressed() const { return (this->flags & (1 << 0)); }
|
||||
constexpr bool IsRoCompressed() const { return (this->flags & (1 << 1)); }
|
||||
constexpr bool IsRwCompressed() const { return (this->flags & (1 << 2)); }
|
||||
constexpr bool Is64Bit() const { return (this->flags & (1 << 3)); }
|
||||
constexpr bool Is64BitAddressSpace() const { return (this->flags & (1 << 4)); }
|
||||
constexpr bool UsesSecureMemory() const { return (this->flags & (1 << 5)); }
|
||||
|
||||
constexpr u32 GetRxAddress() const { return this->rx_address; }
|
||||
constexpr u32 GetRxSize() const { return this->rx_size; }
|
||||
constexpr u32 GetRxCompressedSize() const { return this->rx_compressed_size; }
|
||||
constexpr u32 GetRoAddress() const { return this->ro_address; }
|
||||
constexpr u32 GetRoSize() const { return this->ro_size; }
|
||||
constexpr u32 GetRoCompressedSize() const { return this->ro_compressed_size; }
|
||||
constexpr u32 GetRwAddress() const { return this->rw_address; }
|
||||
constexpr u32 GetRwSize() const { return this->rw_size; }
|
||||
constexpr u32 GetRwCompressedSize() const { return this->rw_compressed_size; }
|
||||
constexpr u32 GetBssAddress() const { return this->bss_address; }
|
||||
constexpr u32 GetBssSize() const { return this->bss_size; }
|
||||
|
||||
constexpr u32 GetAffinityMask() const { return this->affinity_mask; }
|
||||
constexpr u32 GetStackSize() const { return this->stack_size; }
|
||||
};
|
||||
static_assert(sizeof(KInitialProcessHeader) == 0x100);
|
||||
|
||||
class KInitialProcessReader {
|
||||
private:
|
||||
KInitialProcessHeader *kip_header;
|
||||
public:
|
||||
constexpr KInitialProcessReader() : kip_header() { /* ... */ }
|
||||
|
||||
constexpr const u32 *GetCapabilities() const { return this->kip_header->GetCapabilities(); }
|
||||
constexpr size_t GetNumCapabilities() const { return this->kip_header->GetNumCapabilities(); }
|
||||
|
||||
constexpr size_t GetBinarySize() const {
|
||||
return sizeof(*kip_header) + this->kip_header->GetRxCompressedSize() + this->kip_header->GetRoCompressedSize() + this->kip_header->GetRwCompressedSize();
|
||||
}
|
||||
|
||||
constexpr size_t GetSize() const {
|
||||
if (const size_t bss_size = this->kip_header->GetBssSize(); bss_size != 0) {
|
||||
return this->kip_header->GetBssAddress() + this->kip_header->GetBssSize();
|
||||
} else {
|
||||
return this->kip_header->GetRwAddress() + this->kip_header->GetRwSize();
|
||||
}
|
||||
}
|
||||
|
||||
constexpr u8 GetPriority() const { return this->kip_header->GetPriority(); }
|
||||
constexpr u8 GetIdealCore() const { return this->kip_header->GetIdealCore(); }
|
||||
constexpr u32 GetAffinityMask() const { return this->kip_header->GetAffinityMask(); }
|
||||
constexpr u32 GetStackSize() const { return this->kip_header->GetStackSize(); }
|
||||
|
||||
constexpr bool Is64Bit() const { return this->kip_header->Is64Bit(); }
|
||||
constexpr bool Is64BitAddressSpace() const { return this->kip_header->Is64BitAddressSpace(); }
|
||||
constexpr bool UsesSecureMemory() const { return this->kip_header->UsesSecureMemory(); }
|
||||
|
||||
bool Attach(u8 *bin) {
|
||||
if (KInitialProcessHeader *header = reinterpret_cast<KInitialProcessHeader *>(bin); header->IsValid()) {
|
||||
this->kip_header = header;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Result MakeCreateProcessParameter(ams::svc::CreateProcessParameter *out, bool enable_aslr) const;
|
||||
};
|
||||
|
||||
}
|
|
@ -19,6 +19,12 @@ namespace ams::kern {
|
|||
|
||||
namespace {
|
||||
|
||||
struct InitialProcessInfo {
|
||||
KProcess *process;
|
||||
size_t stack_size;
|
||||
s32 priority;
|
||||
};
|
||||
|
||||
KVirtualAddress GetInitialProcessBinaryAddress() {
|
||||
return KMemoryLayout::GetPageTableHeapRegion().GetEndAddress() - InitialProcessBinarySizeMax;
|
||||
}
|
||||
|
@ -32,6 +38,59 @@ namespace ams::kern {
|
|||
MESOSPHERE_ABORT_UNLESS(header->num_processes <= init::GetSlabResourceCounts().num_KProcess);
|
||||
}
|
||||
|
||||
void CreateProcesses(InitialProcessInfo *infos, KVirtualAddress binary_address, const InitialProcessBinaryHeader &header) {
|
||||
u8 *current = GetPointer<u8>(binary_address + sizeof(InitialProcessBinaryHeader));
|
||||
const u8 * const end = GetPointer<u8>(binary_address + header.size - sizeof(KInitialProcessHeader));
|
||||
|
||||
const size_t num_processes = header.num_processes;
|
||||
for (size_t i = 0; i < num_processes; i++) {
|
||||
/* Validate that we can read the current KIP. */
|
||||
MESOSPHERE_ABORT_UNLESS(current <= end);
|
||||
KInitialProcessReader reader;
|
||||
MESOSPHERE_ABORT_UNLESS(reader.Attach(current));
|
||||
|
||||
/* Parse process parameters and reserve memory. */
|
||||
ams::svc::CreateProcessParameter params;
|
||||
MESOSPHERE_R_ABORT_UNLESS(reader.MakeCreateProcessParameter(std::addressof(params), true));
|
||||
MESOSPHERE_TODO("Reserve memory");
|
||||
|
||||
/* Create the process, and ensure we don't leak pages. */
|
||||
{
|
||||
/* Allocate memory for the process. */
|
||||
MESOSPHERE_TODO("Allocate memory for the process");
|
||||
|
||||
/* Map the process's memory into the temporary region. */
|
||||
MESOSPHERE_TODO("Map the process's page group");
|
||||
|
||||
/* Load the process. */
|
||||
MESOSPHERE_TODO("Load the process");
|
||||
|
||||
/* Unmap the temporary mapping. */
|
||||
MESOSPHERE_TODO("Unmap the process's page group");
|
||||
|
||||
/* Create a KProcess object. */
|
||||
MESOSPHERE_TODO("Create a KProcess");
|
||||
|
||||
/* Initialize the process. */
|
||||
MESOSPHERE_TODO("Initialize the process");
|
||||
}
|
||||
|
||||
/* Set the process's memory permissions. */
|
||||
MESOSPHERE_TODO("Set process's memory permissions");
|
||||
|
||||
/* Register the process. */
|
||||
MESOSPHERE_TODO("Register the process");
|
||||
|
||||
/* Save the process info. */
|
||||
infos[i].process = /* TODO */ nullptr;
|
||||
infos[i].stack_size = reader.GetStackSize();
|
||||
infos[i].priority = reader.GetPriority();
|
||||
|
||||
/* Advance the reader. */
|
||||
current += reader.GetBinarySize();
|
||||
}
|
||||
}
|
||||
|
||||
KVirtualAddress g_initial_process_binary_address;
|
||||
InitialProcessBinaryHeader g_initial_process_binary_header;
|
||||
u64 g_initial_process_id_min = std::numeric_limits<u64>::max();
|
||||
|
@ -71,4 +130,32 @@ namespace ams::kern {
|
|||
}
|
||||
}
|
||||
|
||||
void CreateAndRunInitialProcesses() {
|
||||
/* Allocate space for the processes. */
|
||||
InitialProcessInfo *infos = static_cast<InitialProcessInfo *>(__builtin_alloca(sizeof(InitialProcessInfo) * g_initial_process_binary_header.num_processes));
|
||||
|
||||
/* Create the processes. */
|
||||
CreateProcesses(infos, g_initial_process_binary_address, g_initial_process_binary_header);
|
||||
|
||||
/* Release the memory used by the image. */
|
||||
{
|
||||
const size_t total_size = util::AlignUp(g_initial_process_binary_header.size, PageSize);
|
||||
const size_t num_pages = total_size / PageSize;
|
||||
Kernel::GetMemoryManager().Close(g_initial_process_binary_address, num_pages);
|
||||
Kernel::GetSystemResourceLimit().Release(ams::svc::LimitableResource_PhysicalMemoryMax, total_size);
|
||||
}
|
||||
|
||||
/* Determine the initial process id range. */
|
||||
for (size_t i = 0; i < g_initial_process_binary_header.num_processes; i++) {
|
||||
const auto pid = infos[i].process->GetId();
|
||||
g_initial_process_id_min = std::min(g_initial_process_id_min, pid);
|
||||
g_initial_process_id_max = std::max(g_initial_process_id_max, pid);
|
||||
}
|
||||
|
||||
/* Run the processes. */
|
||||
for (size_t i = 0; i < g_initial_process_binary_header.num_processes; i++) {
|
||||
MESOSPHERE_TODO("infos[i].process->Run(infos[i].priority, infos[i].stack_size);");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
103
libraries/libmesosphere/source/kern_k_address_space_info.cpp
Normal file
103
libraries/libmesosphere/source/kern_k_address_space_info.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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 {
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr uintptr_t Invalid = std::numeric_limits<uintptr_t>::max();
|
||||
|
||||
constexpr KAddressSpaceInfo AddressSpaceInfos[] = {
|
||||
{ .bit_width = 32, .address = 2_MB, .size = 1_GB - 2_MB, KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 32, .address = 1_GB, .size = 4_GB - 1_GB, KAddressSpaceInfo::Type_Small64Bit, },
|
||||
{ .bit_width = 32, .address = Invalid, .size = 1_GB, KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 32, .address = Invalid, .size = 1_GB, KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 36, .address = 128_MB, .size = 2_GB - 128_MB, KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 36, .address = 2_GB, .size = 64_GB - 2_GB, KAddressSpaceInfo::Type_Small64Bit, },
|
||||
{ .bit_width = 36, .address = Invalid, .size = 6_GB, KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 36, .address = Invalid, .size = 6_GB, KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 39, .address = 128_MB, .size = 512_GB - 128_MB, KAddressSpaceInfo::Type_Large64Bit, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 64_GB, KAddressSpaceInfo::Type_32Bit, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 6_GB, KAddressSpaceInfo::Type_Heap, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 64_GB, KAddressSpaceInfo::Type_Alias, },
|
||||
{ .bit_width = 39, .address = Invalid, .size = 2_GB, KAddressSpaceInfo::Type_Stack, },
|
||||
};
|
||||
|
||||
constexpr bool IsAllowedIndexForAddress(size_t index) {
|
||||
return index < util::size(AddressSpaceInfos) && AddressSpaceInfos[index].GetAddress() != Invalid;
|
||||
}
|
||||
|
||||
constexpr size_t AddressSpaceIndices32Bit[KAddressSpaceInfo::Type_Count] = {
|
||||
0, 1, 0, 2, 0, 3,
|
||||
};
|
||||
|
||||
constexpr size_t AddressSpaceIndices36Bit[KAddressSpaceInfo::Type_Count] = {
|
||||
4, 5, 4, 6, 4, 7,
|
||||
};
|
||||
|
||||
constexpr size_t AddressSpaceIndices39Bit[KAddressSpaceInfo::Type_Count] = {
|
||||
9, 8, 8, 10, 12, 11,
|
||||
};
|
||||
|
||||
constexpr bool IsAllowed32BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Large64Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
}
|
||||
|
||||
constexpr bool IsAllowed36BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Large64Bit && type != KAddressSpaceInfo::Type_Stack;
|
||||
}
|
||||
|
||||
constexpr bool IsAllowed39BitType(KAddressSpaceInfo::Type type) {
|
||||
return type < KAddressSpaceInfo::Type_Count && type != KAddressSpaceInfo::Type_Small64Bit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) {
|
||||
switch (width) {
|
||||
case 32:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed32BitType(type));
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[type]));
|
||||
return AddressSpaceInfos[AddressSpaceIndices32Bit[type]].GetAddress();
|
||||
case 36:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed36BitType(type));
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[type]));
|
||||
return AddressSpaceInfos[AddressSpaceIndices36Bit[type]].GetAddress();
|
||||
case 39:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed39BitType(type));
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[type]));
|
||||
return AddressSpaceInfos[AddressSpaceIndices39Bit[type]].GetAddress();
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) {
|
||||
switch (width) {
|
||||
case 32:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed32BitType(type));
|
||||
return AddressSpaceInfos[AddressSpaceIndices32Bit[type]].GetSize();
|
||||
case 36:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed36BitType(type));
|
||||
return AddressSpaceInfos[AddressSpaceIndices36Bit[type]].GetSize();
|
||||
case 39:
|
||||
MESOSPHERE_ABORT_UNLESS(IsAllowed39BitType(type));
|
||||
return AddressSpaceInfos[AddressSpaceIndices39Bit[type]].GetSize();
|
||||
MESOSPHERE_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 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 KInitialProcessReader::MakeCreateProcessParameter(ams::svc::CreateProcessParameter *out, bool enable_aslr) const {
|
||||
/* Get and validate addresses/sizes. */
|
||||
const uintptr_t rx_address = this->kip_header->GetRxAddress();
|
||||
const size_t rx_size = this->kip_header->GetRxSize();
|
||||
const uintptr_t ro_address = this->kip_header->GetRoAddress();
|
||||
const size_t ro_size = this->kip_header->GetRoSize();
|
||||
const uintptr_t rw_address = this->kip_header->GetRwAddress();
|
||||
const size_t rw_size = this->kip_header->GetRwSize();
|
||||
const uintptr_t bss_address = this->kip_header->GetBssAddress();
|
||||
const size_t bss_size = this->kip_header->GetBssSize();
|
||||
R_UNLESS(util::IsAligned(rx_address, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(util::IsAligned(ro_address, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(util::IsAligned(rw_address, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(rx_address <= rx_address + util::AlignUp(rx_size, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(ro_address <= ro_address + util::AlignUp(ro_size, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(rw_address <= rw_address + util::AlignUp(rw_size, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(bss_address <= bss_address + util::AlignUp(bss_size, PageSize), svc::ResultInvalidAddress());
|
||||
R_UNLESS(rx_address + util::AlignUp(rx_size, PageSize) <= ro_address, svc::ResultInvalidAddress());
|
||||
R_UNLESS(ro_address + util::AlignUp(ro_size, PageSize) <= rw_address, svc::ResultInvalidAddress());
|
||||
R_UNLESS(rw_address + rw_size <= bss_address, svc::ResultInvalidAddress());
|
||||
|
||||
/* Validate the address space. */
|
||||
if (this->Is64BitAddressSpace()) {
|
||||
R_UNLESS(this->Is64Bit(), svc::ResultInvalidCombination());
|
||||
}
|
||||
|
||||
using ASType = KAddressSpaceInfo::Type;
|
||||
|
||||
const uintptr_t start_address = rx_address;
|
||||
const uintptr_t end_address = bss_size > 0 ? bss_address + bss_size : rw_address + rw_size;
|
||||
const size_t as_width = this->Is64BitAddressSpace() ? 39 : 32;
|
||||
const ASType as_type = this->Is64BitAddressSpace() ? KAddressSpaceInfo::Type_Large64Bit : KAddressSpaceInfo::Type_32Bit;
|
||||
const uintptr_t map_start = KAddressSpaceInfo::GetAddressSpaceStart(as_width, as_type);
|
||||
const size_t map_size = KAddressSpaceInfo::GetAddressSpaceSize(as_width, as_type);
|
||||
const uintptr_t map_end = map_start + map_size;
|
||||
MESOSPHERE_ABORT_UNLESS(start_address == 0);
|
||||
|
||||
/* Set fields in parameter. */
|
||||
out->code_address = map_start + start_address;
|
||||
out->code_num_pages = util::AlignUp(end_address - start_address, PageSize);
|
||||
out->program_id = this->kip_header->GetProgramId();
|
||||
out->version = this->kip_header->GetVersion();
|
||||
out->flags = 0;
|
||||
MESOSPHERE_ABORT_UNLESS((out->code_address / PageSize) + out->code_num_pages <= (map_end / PageSize));
|
||||
|
||||
/* Copy name field. */
|
||||
this->kip_header->GetName(out->name, sizeof(out->name));
|
||||
|
||||
/* Apply ASLR, if needed. */
|
||||
if (enable_aslr) {
|
||||
const size_t choices = (map_end / KernelAslrAlignment) - (util::AlignUp(out->code_address + out->code_num_pages * PageSize, KernelAslrAlignment) / KernelAslrAlignment);
|
||||
out->code_address += KSystemControl::GenerateRandomRange(0, choices) * KernelAslrAlignment;
|
||||
out->flags |= ams::svc::CreateProcessFlag_EnableAslr;
|
||||
}
|
||||
|
||||
/* Apply other flags. */
|
||||
if (this->Is64Bit()) {
|
||||
out->flags |= ams::svc::CreateProcessFlag_Is64Bit;
|
||||
}
|
||||
if (this->Is64BitAddressSpace()) {
|
||||
out->flags |= ams::svc::CreateProcessFlag_AddressSpace64Bit;
|
||||
} else {
|
||||
out->flags |= ams::svc::CreateProcessFlag_AddressSpace32Bit;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
|
@ -116,7 +116,8 @@ namespace ams::kern {
|
|||
/* Initialize the SMMU. */
|
||||
KDeviceAddressSpace::Initialize();
|
||||
|
||||
MESOSPHERE_TODO("CreateAndRunInitialProcesses();");
|
||||
/* Load the initial processes. */
|
||||
CreateAndRunInitialProcesses();
|
||||
|
||||
/* We're done initializing! */
|
||||
Kernel::SetState(Kernel::State::Initialized);
|
||||
|
|
Loading…
Reference in a new issue