diff --git a/exosphere/src/bootup.c b/exosphere/src/bootup.c index 7dab360d8..d667e692f 100644 --- a/exosphere/src/bootup.c +++ b/exosphere/src/bootup.c @@ -315,7 +315,7 @@ void setup_current_core_state(void) { uint64_t temp_reg; /* Setup system registers. */ - SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b0101); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */ + SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b1001); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */ SET_SYSREG(actlr_el3, 0x73ull); SET_SYSREG(actlr_el2, 0x73ull); diff --git a/fusee/fusee-secondary/src/package2.c b/fusee/fusee-secondary/src/package2.c index 543d962fb..4c7654766 100644 --- a/fusee/fusee-secondary/src/package2.c +++ b/fusee/fusee-secondary/src/package2.c @@ -35,9 +35,10 @@ static void package2_decrypt(package2_header_t *package2); static size_t package2_get_src_section(void **section, package2_header_t *package2, unsigned int id); -static size_t package2_get_thermosphere(void **thermosphere); +static size_t package2_get_thermosphere(const void **thermosphere); static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target_firmware, void *emummc, size_t emummc_size); -static void package2_append_section(unsigned int id, package2_header_t *package2, void *data, size_t size); +static void package2_append_section(unsigned int id, package2_header_t *package2, const void *data, size_t size); +static void package2_fixup_thermosphere_and_entrypoint(package2_header_t *package2); static void package2_fixup_header_and_section_hashes(package2_header_t *package2, size_t size); static inline size_t align_to_4(size_t s) { @@ -50,7 +51,7 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm void *kernel; size_t kernel_size; bool is_sd_kernel = false; - void *thermosphere; + const void *thermosphere; size_t thermosphere_size; ini1_header_t *orig_ini1, *rebuilt_ini1; @@ -67,6 +68,8 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm fatal_error(u8"Error: Package2 has no unused section for Thermosphère!\n"); } + package2->metadata.section_offsets[PACKAGE2_SECTION_UNUSED] = 0; /* base of DRAM */ + /* Load Kernel from SD, if possible. */ { size_t sd_kernel_size = get_file_size("atmosphere/kernel.bin"); @@ -125,6 +128,9 @@ void package2_rebuild_and_copy(package2_header_t *package2, uint32_t target_firm package2_append_section(PACKAGE2_SECTION_INI1, rebuilt_package2, rebuilt_ini1, rebuilt_ini1->size); package2_append_section(PACKAGE2_SECTION_UNUSED, rebuilt_package2, thermosphere, thermosphere_size); + /* Swap entrypoint if Thermosphère is present */ + package2_fixup_thermosphere_and_entrypoint(rebuilt_package2); + /* Fix all necessary data in the header to accomodate for the new patches. */ package2_fixup_header_and_section_hashes(rebuilt_package2, rebuilt_package2_size); @@ -309,12 +315,9 @@ static size_t package2_get_src_section(void **section, package2_header_t *packag return package2->metadata.section_sizes[id]; } -static size_t package2_get_thermosphere(void **thermosphere) { - /*extern const uint8_t thermosphere_bin[]; - extern const uint32_t thermosphere_bin_size;*/ - /* TODO: enable when tested. */ - (*thermosphere) = NULL; - return 0; +static size_t package2_get_thermosphere(const void **thermosphere) { + (*thermosphere) = thermosphere_bin; + return thermosphere_bin_size; } static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target_firmware, void *emummc, size_t emummc_size) { @@ -335,7 +338,7 @@ static ini1_header_t *package2_rebuild_ini1(ini1_header_t *ini1, uint32_t target return merged; } -static void package2_append_section(unsigned int id, package2_header_t *package2, void *data, size_t size) { +static void package2_append_section(unsigned int id, package2_header_t *package2, const void *data, size_t size) { /* This function must be called in ascending order of id. */ /* We assume that the loading address doesn't need to be changed. */ uint8_t *dst = package2->data; @@ -347,6 +350,22 @@ static void package2_append_section(unsigned int id, package2_header_t *package2 package2->metadata.section_sizes[id] = align_to_4(size); } +static void package2_fixup_thermosphere_and_entrypoint(package2_header_t *package2) { + /* Return if Thermosphère is not present */ + if (package2->metadata.section_sizes[PACKAGE2_SECTION_UNUSED] == 0) { + return; + } + + uint8_t *dst = package2->data; + for (unsigned int i = 0; i < PACKAGE2_SECTION_UNUSED; i++) { + dst += package2->metadata.section_sizes[i]; + } + + /* Swap kernel entrypoint with Thermosphère */ + *(uint32_t *)(dst + 4) = DRAM_BASE_PHYSICAL + package2->metadata.entrypoint; + package2->metadata.entrypoint = 0; +} + static void package2_fixup_header_and_section_hashes(package2_header_t *package2, size_t size) { uint8_t *data = package2->data; diff --git a/fusee/fusee-secondary/src/package2.h b/fusee/fusee-secondary/src/package2.h index 9e6206ee3..253e658ce 100644 --- a/fusee/fusee-secondary/src/package2.h +++ b/fusee/fusee-secondary/src/package2.h @@ -55,6 +55,7 @@ #define PACKAGE2_MINVER_910_CURRENT 0xE #define NX_BOOTLOADER_PACKAGE2_LOAD_ADDRESS ((void *)(0xA9800000ull)) +#define DRAM_BASE_PHYSICAL (0x80000000) typedef struct { union { diff --git a/thermosphere/src/start.s b/thermosphere/src/start.s index 4248f5d00..42b0b5654 100644 --- a/thermosphere/src/start.s +++ b/thermosphere/src/start.s @@ -24,9 +24,24 @@ .type _start, %function _start: + b start + +.global g_kernelEntrypoint +g_kernelEntrypoint: + .quad 0 + +start: // Disable interrupts msr daifset, 0b1111 + // Save arg, load entrypoint & spsr + mov x19, x0 + ldr x8, g_kernelEntrypoint + msr elr_el2, x8 + mov x8, #(0b1111 << 6 | 0b0101) // EL1h+DAIF + msr spsr_el2, x8 + eret + // Set VBAR ldr x8, =__vectors_start__ msr vbar_el2, x8 @@ -43,6 +58,10 @@ _start: sub x2, x2, x0 bl memset - b . // FIXME! + // TODO + + // Jump to kernel + mov x0, x19 + eret .pool