kernel_ldr: update to support 10.0.0

This commit is contained in:
Michael Scire 2020-04-14 07:38:01 -07:00
parent 122b0775f1
commit 116e00c21c
5 changed files with 334 additions and 29 deletions

View file

@ -21,6 +21,14 @@
.section .crt0.text.start, "ax", %progbits
.global _start
_start:
b _main
__metadata_begin:
.ascii "MLD0" /* Magic */
__metadata_target_firmware:
.dword 0xCCCCCCCC /* Target Firmware. */
__metadata_reserved:
.dword 0xCCCCCCCC /* Reserved. */
_main:
/* KernelLdr_Main(uintptr_t kernel_base_address, KernelMap *kernel_map, uintptr_t ini1_base_address); */
adr x18, _start
adr x16, __external_references
@ -96,6 +104,14 @@ _start:
mov sp, x2
br x1
.global _ZN3ams4kern17GetTargetFirmwareEv
.type _ZN3ams4kern17GetTargetFirmwareEv, %function
_ZN3ams4kern17GetTargetFirmwareEv:
adr x0, __metadata_target_firmware
ldr x0, [x0]
ret
.balign 8
__external_references:
.quad __bss_start__ - _start

View file

@ -31,12 +31,29 @@ namespace ams::kern::init::loader {
constexpr size_t KernelResourceRegionSize = 0x1728000;
constexpr size_t ExtraKernelResourceSize = 0x68000;
static_assert(ExtraKernelResourceSize + KernelResourceRegionSize == 0x1790000);
constexpr size_t KernelResourceReduction_10_0_0 = 0x10000;
constexpr size_t InitialPageTableRegionSize = 0x200000;
/* Global Allocator. */
KInitialPageAllocator g_initial_page_allocator;
KInitialPageAllocator::State g_final_page_allocator_state;
size_t GetResourceRegionSize() {
/* Decide if Kernel should have enlarged resource region. */
const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
size_t resource_region_size = KernelResourceRegionSize + (use_extra_resources ? ExtraKernelResourceSize : 0);
static_assert(KernelResourceRegionSize > InitialProcessBinarySizeMax);
static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax);
/* 10.0.0 reduced the kernel resource region size by 64K. */
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) {
resource_region_size -= KernelResourceReduction_10_0_0;
}
return resource_region_size;
}
void RelocateKernelPhysically(uintptr_t &base_address, KernelLayout *&layout) {
/* TODO: Proper secure monitor call. */
KPhysicalAddress correct_base = KSystemControl::Init::GetKernelPhysicalBaseAddress(base_address);
@ -100,8 +117,8 @@ namespace ams::kern::init::loader {
cpu::MemoryAccessIndirectionRegisterAccessor(MairValue).Store();
cpu::TranslationControlRegisterAccessor(TcrValue).Store();
/* Perform cpu-specific setup. */
{
/* Perform cpu-specific setup on < 10.0.0. */
if (kern::GetTargetFirmware() < kern::TargetFirmware_10_0_0) {
SavedRegisterState saved_registers;
SaveRegistersToTpidrEl1(&saved_registers);
ON_SCOPE_EXIT { VerifyAndClearTpidrEl1(&saved_registers); };
@ -246,11 +263,8 @@ namespace ams::kern::init::loader {
const uintptr_t init_array_offset = layout->init_array_offset;
const uintptr_t init_array_end_offset = layout->init_array_end_offset;
/* Decide if Kernel should have enlarged resource region. */
const bool use_extra_resources = KSystemControl::Init::ShouldIncreaseThreadResourceLimit();
const size_t resource_region_size = KernelResourceRegionSize + (use_extra_resources ? ExtraKernelResourceSize : 0);
static_assert(KernelResourceRegionSize > InitialProcessBinarySizeMax);
static_assert(KernelResourceRegionSize + ExtraKernelResourceSize > InitialProcessBinarySizeMax);
/* Determine the size of the resource region. */
const size_t resource_region_size = GetResourceRegionSize();
/* Setup the INI1 header in memory for the kernel. */
const uintptr_t ini_end_address = base_address + ini_load_offset + resource_region_size;
@ -290,6 +304,11 @@ namespace ams::kern::init::loader {
ttbr1_table.Map(virtual_base_address + ro_offset, ro_end_offset - ro_offset, base_address + ro_offset, KernelRwDataAttribute, g_initial_page_allocator);
ttbr1_table.Map(virtual_base_address + rw_offset, bss_end_offset - rw_offset, base_address + rw_offset, KernelRwDataAttribute, g_initial_page_allocator);
/* On 10.0.0+, Physicaly randomize the kernel region. */
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) {
ttbr1_table.PhysicallyRandomize(virtual_base_address + rx_offset, bss_end_offset - rx_offset, true);
}
/* Clear kernel .bss. */
std::memset(GetVoidPointer(virtual_base_address + bss_offset), 0, bss_end_offset - bss_offset);
@ -312,7 +331,12 @@ namespace ams::kern::init::loader {
}
uintptr_t GetFinalPageAllocatorState() {
return g_initial_page_allocator.GetFinalState();
g_initial_page_allocator.GetFinalState(std::addressof(g_final_page_allocator_state));
if (kern::GetTargetFirmware() >= kern::TargetFirmware_10_0_0) {
return reinterpret_cast<uintptr_t>(std::addressof(g_final_page_allocator_state));
} else {
return g_final_page_allocator_state.next_address;
}
}
}