]> Chaos Git - corbenik/corbenik.git/commitdiff
Clean up a lot of logic related to the reboot hook.
authorJon Feldman <chaos.kagami@gmail.com>
Thu, 9 Feb 2017 12:41:19 +0000 (07:41 -0500)
committerJon Feldman <chaos.kagami@gmail.com>
Thu, 9 Feb 2017 12:41:19 +0000 (07:41 -0500)
I can confirm that we now get into corbenik's payload on firmlaunch (the good old power off on button approach) but some step of initialization is resulting in a hang. Not there yet, sadly.

bits/Makefile
bits/reboot_code.s [deleted file]
bits/reboot_hook.s
boot/arm11.c
boot/chainloader.c
boot/corbenik.c
boot/patch/reboot.c
bootstub/chainloader.c
include/arm11.h

index 814e965d6c60055241d2449781f09ce598831c34..0ea3a0aef42e6ed2f435032d6be26a33305e087b 100644 (file)
@@ -6,7 +6,7 @@ OBJECTS=$(patsubst %.s, %.bin, $(SOURCES))
 all: $(OBJECTS)
 
 %.o: %.s
-       arm-none-eabi-as -o $@ $<
+       arm-none-eabi-as -I$(shell pwd)/../include -o $@ $<
 
 %.elf: %.o
        arm-none-eabi-ld -T link.ld -o $@ $<
diff --git a/bits/reboot_code.s b/bits/reboot_code.s
deleted file mode 100644 (file)
index de404f2..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-.set firm_addr, 0x24000000  // Temporary location where we'll load the FIRM to
-.set firm_maxsize, 0x200000  // Random value that's bigger than any of the currently known firm's sizes.
-
-.section .text
-.global _start
-_start:
-
-    // Set MPU settings
-    mrc p15, 0, r0, c2, c0, 0  // dcacheable
-    mrc p15, 0, r12, c2, c0, 1  // icacheable
-    mrc p15, 0, r1, c3, c0, 0  // write bufferable
-    mrc p15, 0, r2, c5, c0, 2  // daccess
-    mrc p15, 0, r3, c5, c0, 3  // iaccess
-    ldr r4, =0x18000035  // 0x18000000 128M
-    bic r2, r2, #0xF0000  // unprotect region 4
-    bic r3, r3, #0xF0000  // unprotect region 4
-    orr r0, r0, #0x10  // dcacheable region 4
-    orr r2, r2, #0x30000  // region 4 r/w
-    orr r3, r3, #0x30000  // region 4 r/w
-    orr r12, r12, #0x10  // icacheable region 4
-    orr r1, r1, #0x10  // write bufferable region 4
-    mcr p15, 0, r0, c2, c0, 0
-    mcr p15, 0, r12, c2, c0, 1
-    mcr p15, 0, r1, c3, c0, 0  // write bufferable
-    mcr p15, 0, r2, c5, c0, 2  // daccess
-    mcr p15, 0, r3, c5, c0, 3  // iaccess
-    mcr p15, 0, r4, c6, c4, 0  // region 4 (hmmm)
-
-    mrc p15, 0, r0, c2, c0, 0  // dcacheable
-    mrc p15, 0, r1, c2, c0, 1  // icacheable
-    mrc p15, 0, r2, c3, c0, 0  // write bufferable
-    orr r0, r0, #0x20  // dcacheable region 5
-    orr r1, r1, #0x20  // icacheable region 5
-    orr r2, r2, #0x20  // write bufferable region 5
-    mcr p15, 0, r0, c2, c0, 0  // dcacheable
-    mcr p15, 0, r1, c2, c0, 1  // icacheable
-    mcr p15, 0, r2, c3, c0, 0  // write bufferable
-
-    // Copy the firmware
-    mov r4, #firm_addr
-    add r5, r4, #0x40  // Start of loop
-    add r6, r5, #0x30 * 3  // End of loop (scan 4 entries)
-
-    copy_firm_loop:
-        ldr r0, [r5]
-        cmp r0, #0
-        addne r0, r4  // src
-        ldrne r1, [r5, #4]  // dest
-        ldrne r2, [r5, #8]  // size
-        blne memcpy32
-
-        cmp r5, r6
-        addlo r5, #0x30
-        blo copy_firm_loop
-
-    // Flush cache
-    mov r2, #0
-    mov r1, r2
-    flush_cache:
-        mov r0, #0
-        mov r3, r2, lsl #30
-        flush_cache_inner_loop:
-            orr r12, r3, r0, lsl#5
-            mcr p15, 0, r1, c7, c10, 4  // drain write buffer
-            mcr p15, 0, r12, c7, c14, 2  // clean and flush dcache entry (index and segment)
-            add r0, #1
-            cmp r0, #0x20
-            bcc flush_cache_inner_loop
-        add r2, #1
-        cmp r2, #4
-        bcc flush_cache
-
-    // Enable MPU
-    ldr r0, =0x42078  // alt vector select, enable itcm
-    mcr p15, 0, r0, c1, c0, 0
-    mcr p15, 0, r1, c7, c5, 0  // flush dcache
-    mcr p15, 0, r1, c7, c6, 0  // flush icache
-    mcr p15, 0, r1, c7, c10, 4  // drain write buffer
-    mov r0, #firm_addr
-
-    // Boot FIRM
-    mov r1, #0x1FFFFFFC
-    ldr r2, [r0, #8]  // arm11 entry
-    str r2, [r1]
-    ldr r0, [r0, #0xC]  // arm9 entry
-    bx r0
-.pool
-
-memcpy32:  // memcpy32(void *src, void *dst, unsigned int size)
-    add r2, r0
-    memcpy32_loop:
-        ldmia r0!, {r3}
-        stmia r1!, {r3}
-        cmp r0, r2
-        blo memcpy32_loop
-    bx lr
index 5681b0ecda73f55cc5951836ccec17592d5144bf..18bc43501dcace6db71eff151b4eae2e4233db13 100644 (file)
@@ -1,5 +1,5 @@
-.set firm_addr, 0x24000000  // Temporary location where we'll load the FIRM to
-.set firm_maxsize, 0x200000  // Random value that's bigger than any of the currently known firm's sizes.
+.set load_addr,    0x24F00000
+.set load_maxsize, 0x200000  // Random value that's bigger than corbenik
 
 .section .text
 .global _start
@@ -20,84 +20,25 @@ _start:
         cmp r0, r2
         bne pxi_wait_recv
 
-    // Convert 2 bytes of the path string
-    // This will be the method of getting the lower 2 bytes of the title ID
-    //   until someone bothers figuring out where the value is derived from.
-    mov r0, #0  // Result
-    add r1, sp, #0x3A8 - 0x70
-    add r1, #0x22  // The significant bytes
-    mov r2, #4  // Maximum loops (amount of bytes * 2)
-
-    hex_string_to_int_loop:
-        ldr r3, [r1], #2  // 2 because it's a utf-16 string.
-        and r3, #0xFF
-
-        // Check if it"s a number
-        cmp r3, #'0'
-        blo hex_string_to_int_end
-        sub r3, #'0'
-        cmp r3, #9
-        bls hex_string_to_int_calc
-
-        // Check if it"s a capital letter
-        cmp r3, #'A' - '0'
-        blo hex_string_to_int_end
-        sub r3, #'A' - '0' - 0xA  // Make the correct value: 0xF >= al >= 0xA
-        cmp r3, #0xF
-        bls hex_string_to_int_calc
-
-        // Incorrect value: x > "A"
-        bhi hex_string_to_int_end
-
-        hex_string_to_int_calc:
-            orr r0, r3, r0, lsl #4
-            subs r2, #1
-            bne hex_string_to_int_loop
-    hex_string_to_int_end:
-
-    // Get the FIRM path
-    cmp r0, #0x0002  // NATIVE_FIRM
-    ldreq r1, firm_fname
-    beq check_fname
-
-    ldr r5, =0x0102  // TWL_FIRM
-    cmp r0, r5
-    ldreq r1, twl_firm_fname
-    beq check_fname
-
-    ldr r5, =0x0202  // AGB_FIRM
-    cmp r0, r5
-    ldreq r1, agb_firm_fname
-    beq check_fname
-
-    fallback:
-        // Fallback: Load specified FIRM from exefs
-        add r1, sp, #0x3A8-0x70  // Location of exefs string.
-        b load_firm
-
-    check_fname:
-        // Check the given string offset
-        cmp r1, #0
-        beq fallback
-
-    load_firm:
+    load_file:
         // Open file
         add r0, r7, #8
+        adr r1, boot_fname
         mov r2, #1
         ldr r6, fopen
         orr r6, #1
         blx r6
 
         cmp r0, #0  // Check if we were able to load the FIRM
-        bne fallback  // Otherwise, try again with the FIRM from exefs.
-        // This will loop indefinitely if the exefs FIRM fails to load, but whatever.
+        bne die  // Otherwise, hang.
 
-        // Read file
+    read_file:
+        // Read file to the proper base.
         mov r0, r7
         adr r1, bytes_read
-        mov r2, #firm_addr
-        mov r3, #firm_maxsize
-        ldr r6, [sp, #0x3A8-0x198]
+        ldr r2, =load_addr
+        ldr r3, =load_maxsize
+        ldr r6, [r7]
         ldr r6, [r6, #0x28]
         blx r6
 
@@ -108,18 +49,47 @@ _start:
     mov r3, #0
     swi 0x7C
 
-    // Jump to reboot code
-    ldr r0, reboot_code
-    swi 0x7B
+    jump_to_kernel:
+        // Jump to reboot code in kernel mode
+        ldr r0, koffset_base
+        add r0, pc
+        swi 0x7B
 
     die:
         b die
 
-.align 4
-bytes_read:     .word 0
-fopen:          .ascii "open"
-reboot_code:    .ascii "rebc"
+bytes_read:      .word 0
+fopen:           .ascii "OPEN"
+koffset_base:    .word kernel_code-jump_to_kernel-12
+.pool
+
+kernel_code:
+    // Disable MPU
+    ldr r0, =0x42078
+    mcr p15, 0, r0, c1, c0, 0
+
+    // Flush cache
+    mov r2, #0
+    mov r1, r2
+    flush_cache:
+        mov r0, #0
+        mov r3, r2, lsl #30
+        flush_cache_inner_loop:
+            orr r12, r3, r0, lsl#5
+            mcr p15, 0, r12, c7, c14, 2  // clean and flush dcache entry (index and segment)
+            add r0, #1
+            cmp r0, #0x20
+            bcc flush_cache_inner_loop
+        add r2, #1
+        cmp r2, #4
+        bcc flush_cache
+
+    mcr p15, 0, r1, c7, c10, 4  // drain write buffer
+
+    mcr p15, 0, r1, c7, c5, 0   // Flush icache
+
+    ldr r0, =load_addr
+    bx r0
+
 .pool
-firm_fname:     .ascii "NATF"
-twl_firm_fname: .ascii "TWLF"
-agb_firm_fname: .ascii "AGBF"
+boot_fname:      // This gets appended at insert-time
index 1cc97b7abb9b1c74b6437881c12b7fd41a594a61..54d68928995ffd931d9377bb727add5b32e61d32 100644 (file)
@@ -37,7 +37,6 @@
 #include <ctr9/ctr_cache.h>  // for ctr_cache_clean_and_flush_all
 #include <ctr9/i2c.h>        // for i2cWriteRegister, I2C_DEV_MCU
 #include <malloc.h>          // for memalign
-#include <option.h>          // for get_opt_u32, OPTION_BRIGHTNESS
 #include <std/draw.h>        // for framebuffers
 
 struct framebuffers *framebuffers;
@@ -161,10 +160,10 @@ void set_fb_struct() {
     }
 }
 
-void screen_mode(uint32_t mode) {
+void screen_mode(uint32_t mode, uint32_t bright_level) {
     static uint32_t stride, init_top, init_bottom, bright;
 
-    bright = brightness[get_opt_u32(OPTION_BRIGHTNESS)];
+    bright = brightness[bright_level];
 
     stride = 240;
     switch(mode) {
index 8c4f4d5e98e03c5b652e154a9cb8c10558b510ba..fead36169101b085f1a0ed409a55aeeb377872c8 100644 (file)
@@ -12,6 +12,7 @@
 #include <std/fs.h>            // for crclose, cropen, crread, crsize, recur...
 #include <std/memory.h>        // for memfind, strdup_self
 #include <structures.h>        // for PATH_BITS, PATH_CHAINS
+#include <option.h>        // for get_opt_u32
 #include "ctr9/io/fatfs/ff.h"  // for FILINFO, f_stat, ::FR_OK, AM_DIR
 
 uint32_t current_chain_index = 0;
@@ -58,7 +59,7 @@ void chainload_file(void* data)
 
     fprintf(stderr, "Changing display mode and chainloading...\n");
 
-    screen_mode(1); // Because RGBA8 screeninit is non-standard...ugh
+    screen_mode(1, get_opt_u32(OPTION_BRIGHTNESS)); // Because RGBA8 screeninit is non-standard...ugh
 
     // Copy CakeHax struct where it is expected (at 0x23FFFE00)
     // It's very very likely we'll corrupt memory with this, but we aren't coming back anyways as of the
index 4a192eab827a8fd3403da2958e8ff016936a6c2e..737ec27610a0f91f50fab23831406179166aa98b 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <arm11.h>         // for screen_mode, RGBA8, installArm11Stub, set_...
 #include <ctr9/ctr_hid.h>  // for ctr_hid_get_buttons, CTR_HID_RT
+#include <ctr9/ctr_system.h>  // for ctr_system_poweroff
 #include <firm/headers.h>     // for prepatch_firm, boot_firm
 #include <firm/firm.h>     // for prepatch_firm, boot_firm
 #include <input.h>         // for wait
@@ -26,6 +27,9 @@ extern int changed_consoles;
 int
 main(int argc, char** argv)
 {
+    if (ctr_hid_get_buttons() & CTR_HID_LT)
+        ctr_system_poweroff();
+
     int have_bg = 0;
     int si = 0;
 
@@ -37,7 +41,7 @@ main(int argc, char** argv)
     std_init();
 
     if (crmount())
-        poweroff(); // Failed to mount SD. Bomb out.
+        ctr_system_poweroff(); // We can't use poweroff here, since that does n/a cleanup that will cause a hang.
 
     load_config(); // Load configuration.
 
@@ -69,7 +73,7 @@ main(int argc, char** argv)
                 shut_up(); // This does exactly what it sounds like.
 
             if (have_bg && !si) {
-                screen_mode(RGBA8); // Use RGBA8 mode.
+                screen_mode(RGBA8, get_opt_u32(OPTION_BRIGHTNESS)); // Use RGBA8 mode.
                 si = 1;
 
                 clear_disp(TOP_SCREEN);
@@ -77,7 +81,7 @@ main(int argc, char** argv)
             }
         } else {
             if (!si) {
-                screen_mode(RGBA8); // Use RGBA8 mode.
+                screen_mode(RGBA8, get_opt_u32(OPTION_BRIGHTNESS)); // Use RGBA8 mode.
                 si = 1;
 
                 clear_disp(TOP_SCREEN);
index b31fb3edb4ce682632651ddf5c4163f390a080f0..5f423a24300725522c458671e2867bd42a8f5e07 100644 (file)
 uint8_t*
 getProcess9(uint8_t *pos, uint32_t size, uint32_t *process9Size, uint32_t *process9MemAddr)
 {
-    uint8_t *off = memfind(pos, size, "ess9", 4);
-    *process9Size = *(uint32_t *)(off - 0x60) * 0x200;
-    *process9MemAddr = *(uint32_t *)(off + 0xC);
+    uint8_t *magic = memfind(pos, size, "NCCH", 4);
+    cxi_h* cxi = (cxi_h*)(magic - 0x100);
+
+    *process9Size = (cxi->ncch.exeFSSize - 1) * 0x200;
+    *process9MemAddr = cxi->exheader.sci.textCodeSet.address;
+
     // Process9 code offset (start of NCCH + ExeFS offset + ExeFS header size)
-    return off - 0x204 + (*(uint32_t *)(off - 0x64) * 0x200) + 0x200;
+    return (uint8_t*)cxi + (cxi->ncch.exeFSOffset + 1) * 0x200;
 }
 
 int
@@ -30,9 +33,10 @@ patch_reboot(firm_h* firm_loc)
 
     uint32_t process9Size, process9MemAddr;
     uint8_t *process9Offset =
-        getProcess9((uint8_t *)firm_loc + firm_loc->section[2].offset + 0x15000, firm_loc->section[2].size - 0x15000, &process9Size, &process9MemAddr);
+        getProcess9((uint8_t *)firm_loc + firm_loc->section[2].offset, firm_loc->section[2].size, &process9Size, &process9MemAddr);
 
     fprintf(stderr, "reboot: proc9 mem @ %lx\n", (uint32_t)process9MemAddr);
+    fprintf(stderr, "reboot: proc9 off @ %lx\n", (uint32_t)process9Offset);
 
     wait();
 
@@ -48,7 +52,7 @@ patch_reboot(firm_h* firm_loc)
     // Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
     uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - (uint32_t)process9Offset + process9MemAddr);
 
-    fprintf(stderr, "reboot: cropen @ %lx\n", fOpenOffset);
+    fprintf(stderr, "reboot: fopen @ %lx\n", fOpenOffset);
 
     wait();
 
@@ -62,65 +66,23 @@ patch_reboot(firm_h* firm_loc)
     crclose(f);
 
     // Put the fOpen offset in the right location
-    uint32_t *pos_cropen = (uint32_t *)memfind(off, size, "open", 4);
-    if (!pos_cropen)
+    uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "OPEN", 4);
+    if (!pos_fopen)
         return 1;
 
-    *pos_cropen = fOpenOffset;
+    *pos_fopen = fOpenOffset;
 
-    uint32_t *pos_native = (uint32_t *)memfind(off, size, "NATF", 4);
-    uint32_t *pos_twl = (uint32_t *)memfind(off, size, "TWLF", 4);
-    uint32_t *pos_agb = (uint32_t *)memfind(off, size, "AGBF", 4);
-
-    if (!pos_native && !pos_twl && !pos_agb)
-        return 1;
+    // The path is positioned at the end of our assembly to avoid reservation of space.
+    // We append it here.
+    uint8_t path[] = "sdmc:" PATH_BITS "/corbenik.bin";
 
-    fprintf(stderr, "reboot: NATF @ %lx\n", (uint32_t)pos_native);
-    fprintf(stderr, "reboot: TWLF @ %lx\n", (uint32_t)pos_twl);
-    fprintf(stderr, "reboot: AGBF @ %lx\n", (uint32_t)pos_agb);
-
-    uint8_t *mem = (uint8_t *)0x01FF8000; // 0x8000 space that will be resident. This is AXI WRAM. We have about 0x3700 bytes here.
-    // According to 3dbrew, this space's props from userland:
-    //   [L2L] VA fff00000..fff20000 -> PA 1ff80000..1ffa0000 [  X ] [ Priv: R-, User: -- ]
-    // It can be executed by the system but not written (and can only be executed with privs)
-    // This seems to be the perfect place to stick some code to be resident in memory. Beyond this,
-    // it might be needed to replace a svc call to access it. I'm rather sure that NTR does this.
-
-    *pos_native = (uint32_t)mem;
-    memcpy(mem, u"sdmc:", 10);
-    mem += 10;
-    for (size_t i = 0; i < sizeof(PATH_NATIVE_P); i++, mem += 2) {
-        *mem = PATH_NATIVE_P[i];
-        *(mem + 1) = 0;
-    }
-
-    *pos_twl = (uint32_t)mem;
-    memcpy(mem, u"sdmc:", 10);
-    mem += 10;
-    for (size_t i = 0; i < sizeof(PATH_TWL_P); i++, mem += 2) {
-        *mem = PATH_TWL_P[i];
-        *(mem + 1) = 0;
-    }
+    uint16_t *pos = (uint16_t*)(off + size);
 
-    *pos_agb = (uint32_t)mem;
-    memcpy(mem, u"sdmc:", 10);
-    mem += 10;
-    for (size_t i = 0; i < sizeof(PATH_AGB_P); i++, mem += 2) {
-        *mem = PATH_AGB_P[i];
-        *(mem + 1) = 0;
+    for(int i=0; path[i] != 0; i++) {
+        pos[0] = path[i];
+        pos++;
     }
-
-    uint32_t *pos_rebc = (uint32_t *)memfind(off, size, "rebc", 4);
-    *pos_rebc = (uint32_t)mem;
-
-    fprintf(stderr, "reboot: rebc @ %lx\n", (uint32_t)pos_rebc);
-
-    f = cropen(PATH_REBOOT_CODE, "r");
-    if (!f)
-        return 1;
-
-    crread(mem, 1, crsize(f), f);
-    crclose(f);
+    pos[0] = 0;
 
     return 0;
 }
index 688d4d53a626c64812ea4a19dc51067a201524d3..c0d921e2d2de0f699dc6308105d753637edcd1e7 100644 (file)
@@ -2,6 +2,9 @@
 #include <stdlib.h>            // for NULL
 #include <string.h>            // for memcpy, strlen, strncpy
 
+#include <ctr9/ctr_system.h>
+#include <ctr9/ctr_cache.h>
+
 #include <structures.h>
 #include <std/fs.h>
 #include <std/memory.h>
@@ -9,7 +12,7 @@
 
 __attribute__((noreturn))
 void panic() {
-    memset(*(uint8_t**)(0x23FFFE00), 0xFF, 320*240*3);
+    ctr_system_poweroff();
     while(1);
 }
 
@@ -42,8 +45,9 @@ int main()
     memmove(bootstrap, memory, size); // Memory is now clobbered. Any memory allocation is unsafe past this point.
 
     // Set args = 2, { PATH_BITS "/corbenik.bin", "-native" }
+    ctr_cache_clean_and_flush_all();
 
-    ((int(*)(int, char**))bootstrap)(0, 0);
+    ((int(*)(int, char**))bootstrap)(0, NULL);
 
     panic();
 }
index 983cbd989bf168a65d9c69fca5ed4e0a281afc31..57e9c8f8efc3b75ccf0f5f4c559eaef1c66d146c 100644 (file)
@@ -47,7 +47,7 @@
  *
  * \param mode Screen mode to initialize in, one of RGBA8, BGR8, RGB565_OES, RGB5_A1_OES, or RGBA4_OES
  */
-void screen_mode(uint32_t mode);
+void screen_mode(uint32_t mode, uint32_t bright_level);
 
 /* Invokes a bare ARM11 function. For usage, see arm11.c.
  *