kern/ldr: move crt0 into .rodata

This commit is contained in:
Michael Scire 2023-10-11 02:59:41 -07:00
parent 2a060d2645
commit 3f619a1fef
7 changed files with 220 additions and 90 deletions

View file

@ -33,7 +33,37 @@
adr reg, label; \
ldr reg, [reg]
#define LOAD_RELATIVE_FROM_LABEL(reg, reg2, label) \
adr reg2, label; \
ldr reg, [reg2]; \
add reg, reg, reg2
#define INDIRECT_RELATIVE_CALL(reg, reg2, label) \
adr reg, label; \
add reg, reg, reg2; \
blr reg
#define SETUP_SYSTEM_REGISTER(_reg, _sr) \
LOAD_FROM_LABEL(_reg, __sysreg_constant_ ## _sr); \
msr _sr, _reg
.section .start, "ax", %progbits
.global _start
_start:
b _ZN3ams4kern4init10StartCore0Emm
__metadata_magic_number:
.ascii "MSS1" /* Magic, if executed as gadget "adds w13, w26, #0x4d4, lsl #12" */
__metadata_offset:
.word __metadata_begin - _start
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
.global _ZN3ams4kern17GetTargetFirmwareEv
.type _ZN3ams4kern17GetTargetFirmwareEv, %function
_ZN3ams4kern17GetTargetFirmwareEv:
adr x0, __metadata_target_firmware
ldr w0, [x0]
ret
#endif
.section .crt0.text.start, "ax", %progbits
@ -45,43 +75,6 @@ _ZN3ams4kern4init31IdentityMappedFunctionAreaBeginEv:
/* ================ Functions after this line remain identity-mapped after initialization finishes. ================ */
.global _start
_start:
b _ZN3ams4kern4init10StartCore0Emm
__metadata_begin:
.ascii "MSS0" /* Magic */
__metadata_ini_offset:
.quad 0 /* INI1 base address. */
__metadata_kernelldr_offset:
.quad 0 /* Kernel Loader base address. */
__metadata_target_firmware:
.word 0xCCCCCCCC /* Target firmware. */
__metadata_kernel_layout:
.word _start - _start /* rx_offset */
.word __rodata_start - _start /* rx_end_offset */
.word __rodata_start - _start /* ro_offset */
.word __data_start - _start /* ro_end_offset */
.word __data_start - _start /* rw_offset */
.word __bss_start__ - _start /* rw_end_offset */
.word __bss_start__ - _start /* bss_offset */
.word __bss_end__ - _start /* bss_end_offset */
.word __end__ - _start /* resource_offset */
.word _DYNAMIC - _start /* dynamic_offset */
.word __init_array_start - _start /* init_array_offset */
.word __init_array_end - _start /* init_array_end_offset */
.if (. - __metadata_begin) != 0x48
.error "Incorrect Mesosphere Metadata"
.endif
#ifdef ATMOSPHERE_BOARD_NINTENDO_NX
.global _ZN3ams4kern17GetTargetFirmwareEv
.type _ZN3ams4kern17GetTargetFirmwareEv, %function
_ZN3ams4kern17GetTargetFirmwareEv:
adr x0, __metadata_target_firmware
ldr w0, [x0]
ret
#endif
/* ams::kern::init::StartCore0(uintptr_t, uintptr_t) */
.section .crt0.text._ZN3ams4kern4init10StartCore0Emm, "ax", %progbits
.global _ZN3ams4kern4init10StartCore0Emm
@ -139,28 +132,31 @@ _ZN3ams4kern4init10StartCore0Emm:
/* Get the unknown debug region. */
/* TODO: This is always zero in release kernels -- what is this? Is it the device tree buffer? */
mov x21, #0
nop
/* We want to invoke kernel loader. */
adr x0, _start
adr x1, __metadata_kernel_layout
LOAD_FROM_LABEL(x2, __metadata_ini_offset)
add x2, x0, x2
LOAD_FROM_LABEL(x3, __metadata_kernelldr_offset)
add x3, x0, x3
LOAD_RELATIVE_FROM_LABEL(x2, x4, __metadata_ini_offset)
LOAD_RELATIVE_FROM_LABEL(x3, x4, __metadata_kernelldr_offset)
/* Invoke kernel loader. */
blr x3
/* Save the offset to virtual address from this page's physical address for our use. */
mov x24, x1
/* At this point kernelldr has been invoked, and we are relocated at a random virtual address. */
/* Next thing to do is to set up our memory management and slabheaps -- all the other core initialization. */
/* Call ams::kern::init::InitializeCore(uintptr_t, void **) */
mov x1, x0 /* Kernelldr returns a state object for the kernel to re-use. */
mov x0, x21 /* Use the address we determined earlier. */
bl _ZN3ams4kern4init20InitializeCorePhase1EmPPv
INDIRECT_RELATIVE_CALL(x16, x24, _ZN3ams4kern4init20InitializeCorePhase1EmPPv)
/* Get the init arguments for core 0. */
mov x0, xzr
bl _ZN3ams4kern4init16GetInitArgumentsEi
nop
INDIRECT_RELATIVE_CALL(x16, x24, _ZN3ams4kern4init16GetInitArgumentsEi)
/* Setup the stack pointer. */
ldr x2, [x0, #(INIT_ARGUMENTS_SP)]
@ -168,15 +164,24 @@ _ZN3ams4kern4init10StartCore0Emm:
/* Perform further initialization with the stack pointer set up, as required. */
/* This will include e.g. unmapping the identity mapping. */
bl _ZN3ams4kern4init20InitializeCorePhase2Ev
INDIRECT_RELATIVE_CALL(x16, x24, _ZN3ams4kern4init20InitializeCorePhase2Ev)
/* Get the init arguments for core 0. */
mov x0, xzr
bl _ZN3ams4kern4init16GetInitArgumentsEi
nop
INDIRECT_RELATIVE_CALL(x16, x24, _ZN3ams4kern4init16GetInitArgumentsEi)
/* Invoke the entrypoint. */
/* Retrieve entrypoint and argument. */
ldr x1, [x0, #(INIT_ARGUMENTS_ENTRYPOINT)]
ldr x0, [x0, #(INIT_ARGUMENTS_ARGUMENT)]
/* Set sctlr_el1 and ensure instruction consistency. */
SETUP_SYSTEM_REGISTER(x3, sctlr_el1)
dsb sy
isb
/* Invoke the entrypoint. */
blr x1
0: /* If we return here, something has gone wrong, so wait forever. */
@ -218,15 +223,11 @@ _ZN3ams4kern4init14StartOtherCoreEPKNS1_14KInitArgumentsE:
/* Disable the MMU/Caches. */
bl _ZN3ams4kern4init19DisableMmuAndCachesEv
/* Setup system registers using values from our KInitArguments. */
ldr x1, [x20, #(INIT_ARGUMENTS_TTBR0)]
msr ttbr0_el1, x1
ldr x1, [x20, #(INIT_ARGUMENTS_TTBR1)]
msr ttbr1_el1, x1
ldr x1, [x20, #(INIT_ARGUMENTS_TCR)]
msr tcr_el1, x1
ldr x1, [x20, #(INIT_ARGUMENTS_MAIR)]
msr mair_el1, x1
/* Setup system registers using values from constants table. */
SETUP_SYSTEM_REGISTER(x1, ttbr0_el1)
SETUP_SYSTEM_REGISTER(x1, ttbr1_el1)
SETUP_SYSTEM_REGISTER(x1, tcr_el1)
SETUP_SYSTEM_REGISTER(x1, mair_el1)
/* Perform cpu-specific setup. */
mrs x1, midr_el1
@ -251,13 +252,12 @@ _ZN3ams4kern4init14StartOtherCoreEPKNS1_14KInitArgumentsE:
isb
/* Load remaining needed fields from the init args. */
ldr x3, [x20, #(INIT_ARGUMENTS_SCTLR)]
ldr x2, [x20, #(INIT_ARGUMENTS_SP)]
ldr x1, [x20, #(INIT_ARGUMENTS_ENTRYPOINT)]
ldr x0, [x20, #(INIT_ARGUMENTS_ARGUMENT)]
/* Set sctlr_el1 and ensure instruction consistency. */
msr sctlr_el1, x3
SETUP_SYSTEM_REGISTER(x3, sctlr_el1)
dsb sy
isb
@ -271,6 +271,35 @@ _ZN3ams4kern4init14StartOtherCoreEPKNS1_14KInitArgumentsE:
0: /* If we return here, something has gone wrong, so wait forever. */
b 0b
/* Nintendo places the metadata after StartOthercore. */
.align 8
__metadata_begin:
__metadata_ini_offset:
.quad 0 /* INI1 base address. */
__metadata_kernelldr_offset:
.quad 0 /* Kernel Loader base address. */
__metadata_target_firmware:
.word 0xCCCCCCCC /* Target firmware. */
__metadata_kernel_layout:
.word _start - __metadata_kernel_layout /* rx_offset */
.word __rodata_start - __metadata_kernel_layout /* rx_end_offset */
.word __rodata_start - __metadata_kernel_layout /* ro_offset */
.word __data_start - __metadata_kernel_layout /* ro_end_offset */
.word __data_start - __metadata_kernel_layout /* rw_offset */
.word __bss_start__ - __metadata_kernel_layout /* rw_end_offset */
.word __bss_start__ - __metadata_kernel_layout /* bss_offset */
.word __bss_end__ - __metadata_kernel_layout /* bss_end_offset */
.word __end__ - __metadata_kernel_layout /* resource_offset */
.word _DYNAMIC - __metadata_kernel_layout /* dynamic_offset */
.word __init_array_start - __metadata_kernel_layout /* init_array_offset */
.word __init_array_end - __metadata_kernel_layout /* init_array_end_offset */
.word __sysreg_constant_begin - __metadata_kernel_layout /* sysreg_offset */
.if (. - __metadata_begin) != 0x48
.error "Incorrect Mesosphere Metadata"
.endif
/* TODO: Can we remove this while retaining QEMU support? */
#ifndef ATMOSPHERE_BOARD_NINTENDO_NX
/* ams::kern::init::JumpFromEL2ToEL1() */
@ -564,6 +593,24 @@ _ZN3ams4kern4arch5arm643cpu36FlushEntireDataCacheImplWithoutStackEv:
ret
/* System register values. */
.align 8
__sysreg_constant_begin:
__sysreg_constant_ttbr0_el1:
.quad 0 /* ttbr0_e11. */
__sysreg_constant_ttbr1_el1:
.quad 0 /* ttbr1_e11. */
__sysreg_constant_tcr_el1:
.quad 0 /* tcr_e11. */
__sysreg_constant_mair_el1:
.quad 0 /* mair_e11. */
__sysreg_constant_sctlr_el1:
.quad 0 /* sctlr_e11. */
.if (. - __sysreg_constant_begin) != 0x28
.error "Incorrect System Registers"
.endif
/* ================ Functions before this line remain identity-mapped after initialization finishes. ================ */
/* ams::kern::init::IdentityMappedFunctionAreaEnd() */