From dd21a3930d6762d91c5b16c090bc8cd968160c22 Mon Sep 17 00:00:00 2001 From: TuxSH Date: Tue, 23 May 2017 13:33:32 +0200 Subject: [PATCH] Adapt changes from b9s/next --- Makefile | 2 +- arm11/Makefile | 4 ++-- arm11/linker.ld | 3 ++- arm11/source/main.c | 27 ++++++++++++--------------- arm11/source/start.s | 28 ++++++++++++++++++++++++++-- arm11/source/types.h | 7 +++---- loader/Makefile | 4 ++-- loader/source/firm.c | 11 +++-------- loader/source/main.c | 16 ++++++++++++---- loader/source/start.s | 31 +++++++++++++++++++++++++++++++ loader/source/types.h | 8 +++++++- patches/reboot.s | 2 +- source/firm.c | 1 + source/fs.c | 6 ++---- source/screen.c | 5 +++-- source/screen.h | 11 +++++------ 16 files changed, 113 insertions(+), 53 deletions(-) diff --git a/Makefile b/Makefile index a9a9475..063705c 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ dir_out := out ASFLAGS := -mcpu=arm946e-s CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostartfiles +LDFLAGS := -nostartfiles -Wl,--nmagic objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ diff --git a/arm11/Makefile b/arm11/Makefile index 47ddde6..3cb816c 100644 --- a/arm11/Makefile +++ b/arm11/Makefile @@ -13,8 +13,8 @@ dir_build := build dir_out := ../$(dir_build) ASFLAGS := -mcpu=mpcore -CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib -Wl,--nmagic +CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math +LDFLAGS := -nostartfiles -Wl,--nmagic objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ diff --git a/arm11/linker.ld b/arm11/linker.ld index 71d4f80..949304f 100644 --- a/arm11/linker.ld +++ b/arm11/linker.ld @@ -4,11 +4,12 @@ OUTPUT_ARCH(arm) ENTRY(_start) SECTIONS { - . = 0x1FFFE000; + . = 0x1FF80000; .text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); } .rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); } .data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); } + __stack_top__ = 0x1FFFF000; . = ALIGN(4); } diff --git a/arm11/source/main.c b/arm11/source/main.c index fb18a7f..deb9e7e 100644 --- a/arm11/source/main.c +++ b/arm11/source/main.c @@ -27,7 +27,10 @@ #include "types.h" #include "memory.h" -static volatile Arm11Operation *operation = (volatile Arm11Operation *)0x1FFFFFF0; +void prepareForFirmlaunch(void); +extern u32 prepareForFirmlaunchSize; + +extern volatile Arm11Operation operation; static void initScreensSequence(u32 brightnessLevel) { @@ -160,23 +163,16 @@ static void deinitScreens(void) *(vu32 *)0x10202014 = 0; } -static void prepareForFirmlaunch(void) -{ - *ARM11_CORE0_MAILBOX_ENTRYPOINT = 0; - while(*ARM11_CORE0_MAILBOX_ENTRYPOINT == 0); - ((void (*)(void))*ARM11_CORE0_MAILBOX_ENTRYPOINT)(); -} - void main(void) { - *operation = NO_ARM11_OPERATION; + operation = ARM11_READY; while(true) { - switch(*operation) + switch(operation) { - case NO_ARM11_OPERATION: - break; + case ARM11_READY: + continue; case INIT_SCREENS_SEQUENCE: initScreensSequence(*(vu32 *)ARM11_PARAMETERS_ADDRESS); break; @@ -196,12 +192,13 @@ void main(void) deinitScreens(); break; case PREPARE_ARM11_FOR_FIRMLAUNCH: - memcpy((void *)0x1FFFFC00, (void *)prepareForFirmlaunch, 0x2C); - *operation = NO_ARM11_OPERATION; + memcpy((void *)0x1FFFFC00, (void *)prepareForFirmlaunch, prepareForFirmlaunchSize); + *(vu32 *)0x1FFFFFFC = 0; + operation = ARM11_READY; ((void (*)(void))0x1FFFFC00)(); break; } - *operation = NO_ARM11_OPERATION; + operation = ARM11_READY; } } diff --git a/arm11/source/start.s b/arm11/source/start.s index baeaa3f..429f2a2 100644 --- a/arm11/source/start.s +++ b/arm11/source/start.s @@ -17,11 +17,35 @@ @ Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified @ reasonable legal notices or author attributions in that material or in the Appropriate Legal @ Notices displayed by works containing it. - + .section .text.start .align 4 .global _start +.type _start, %function _start: +b start + +.global operation +operation: + .word 0 + +start: cpsid aif - ldr sp, =0x1FFFE000 + ldr sp, =__stack_top__ b main + +.global prepareForFirmlaunch +.type prepareForFirmlaunch, %function +prepareForFirmlaunch: + mov r0, #0x20000000 + + _wait_for_core0_entrypoint_loop: + ldr r1, [r0, #-4] @ check if core0's entrypoint is 0 + cmp r1, #0 + beq _wait_for_core0_entrypoint_loop + + bx r1 @ jump to core0's entrypoint +prepareForFirmlaunchEnd: + +.global prepareForFirmlaunchSize +prepareForFirmlaunchSize: .word prepareForFirmlaunchEnd - prepareForFirmlaunch diff --git a/arm11/source/types.h b/arm11/source/types.h index e29878b..a07e2ef 100644 --- a/arm11/source/types.h +++ b/arm11/source/types.h @@ -40,8 +40,7 @@ typedef volatile u64 vu64; #define SCREEN_HEIGHT 240 #define SCREEN_TOP_FBSIZE (3 * SCREEN_TOP_WIDTH * SCREEN_HEIGHT) #define SCREEN_BOTTOM_FBSIZE (3 * SCREEN_BOTTOM_WIDTH * SCREEN_HEIGHT) -#define ARM11_CORE0_MAILBOX_ENTRYPOINT ((vu32 *)0x1FFFFFFC) -#define ARM11_PARAMETERS_ADDRESS 0x1FFFC000 +#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000 struct fb { u8 *top_left; @@ -51,12 +50,12 @@ struct fb { typedef enum { - NO_ARM11_OPERATION = 0, - INIT_SCREENS_SEQUENCE, + INIT_SCREENS_SEQUENCE = 0, SETUP_FRAMEBUFFERS, CLEAR_SCREENS, SWAP_FRAMEBUFFERS, UPDATE_BRIGHTNESS, DEINIT_SCREENS, PREPARE_ARM11_FOR_FIRMLAUNCH, + ARM11_READY, } Arm11Operation; diff --git a/loader/Makefile b/loader/Makefile index b33944c..6ab2a45 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -13,8 +13,8 @@ dir_build := build dir_out := ../$(dir_build) ASFLAGS := -mcpu=arm946e-s -CFLAGS := -Wall -Wextra -mthumb $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib +CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math +LDFLAGS := -nostartfiles -Wl,--nmagic objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ diff --git a/loader/source/firm.c b/loader/source/firm.c index 776d306..7f8ee91 100644 --- a/loader/source/firm.c +++ b/loader/source/firm.c @@ -24,20 +24,15 @@ #include "memory.h" #include "cache.h" +void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry); + void launchFirm(Firm *firm, int argc, char **argv) { //Copy FIRM sections to respective memory locations for(u32 sectionNum = 0; sectionNum < 4 && firm->section[sectionNum].size != 0; sectionNum++) memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size); - //Ensure that all memory transfers have completed and that the caches have been flushed - flushCaches(); - - //Set ARM11 entrypoint - *(vu32 *)0x1FFFFFFC = (u32)firm->arm11Entry; - - //Jump to ARM9 entrypoint. Also give it additional arguments it can dismiss - ((void (*)(int, char**, u32))firm->arm9Entry)(argc, argv, 0x0000BEEF); + disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry); __builtin_unreachable(); } diff --git a/loader/source/main.c b/loader/source/main.c index 2446297..4bfda93 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -24,17 +24,25 @@ #include "cache.h" #include "firm.h" -void main(int argc __attribute__((unused)), char **argv) +void main(int argc, char **argv) { - Firm *firm = (Firm *)0x24000000; + Firm *firm = (Firm *)0x20001000; + struct fb fbs[2]; char absPath[24 + 255]; + if(argc == 2) + { + struct fb *fbsrc = (struct fb *)argv[1]; + fbs[0] = fbsrc[0]; + fbs[1] = fbsrc[1]; + } + u32 i; for(i = 0; i < sizeof(absPath) - 1 && argv[0][i] != 0; i++) absPath[i] = argv[0][i]; absPath[i] = 0; - char *argvPassed[1] = {absPath}; + char *argvPassed[2] = {absPath, (char *)&fbs}; - launchFirm(firm, 1, argvPassed); + launchFirm(firm, argc, argvPassed); } diff --git a/loader/source/start.s b/loader/source/start.s index 3d1f7c5..4bd3096 100644 --- a/loader/source/start.s +++ b/loader/source/start.s @@ -18,9 +18,40 @@ @ reasonable legal notices or author attributions in that material or in the Appropriate Legal @ Notices displayed by works containing it. +.arm + .section .text.start .align 4 .global _start _start: ldr sp, =0x27ffe000 b main + +.text +.balign 4 +.global disableMpuAndJumpToEntrypoints +.type disableMpuAndJumpToEntrypoints, %function +disableMpuAndJumpToEntrypoints: + mov r4, r0 + mov r5, r1 + mov r6, r2 + mov r7, r3 + + bl flushCaches + + @ Disable caches / MPU + mrc p15, 0, r0, c1, c0, 0 @ read control register + bic r0, #(1<<12) @ - instruction cache disable + bic r0, #(1<<2) @ - data cache disable + bic r0, #(1<<0) @ - mpu disable + mcr p15, 0, r0, c1, c0, 0 @ write control register + + @ Set the ARM11 entrypoint + mov r0, #0x20000000 + str r7, [r0, #-4] + + @ Jump to the ARM9 entrypoint + mov r0, r4 + mov r1, r5 + ldr r2, =0xBEEF + bx r6 diff --git a/loader/source/types.h b/loader/source/types.h index 6a1677e..e6f1216 100644 --- a/loader/source/types.h +++ b/loader/source/types.h @@ -32,4 +32,10 @@ typedef uint64_t u64; typedef volatile u8 vu8; typedef volatile u16 vu16; typedef volatile u32 vu32; -typedef volatile u64 vu64; \ No newline at end of file +typedef volatile u64 vu64; + +struct fb { + u8 *top_left; + u8 *top_right; + u8 *bottom; +} __attribute__((packed)); diff --git a/patches/reboot.s b/patches/reboot.s index 84228a5..c805572 100644 --- a/patches/reboot.s +++ b/patches/reboot.s @@ -7,7 +7,7 @@ fname_addr equ 0x27FFDF80 low_tid_addr equ 0x27FFDFE0 copy_launch_stub_addr equ 0x27FFE000 -firm_addr equ 0x24000000 +firm_addr equ 0x20001000 firm_maxsize equ (copy_launch_stub_addr - 0x1000 - firm_addr) arm11_entrypoint_addr equ 0x1FFFFFFC diff --git a/source/firm.c b/source/firm.c index afdaa75..4cff6be 100755 --- a/source/firm.c +++ b/source/firm.c @@ -443,6 +443,7 @@ bool checkFirmPayload(void) (section->address + section->size < section->address) || //Overflow check ((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF) || //Alignment check (overlaps((u32)section->address, (u32)section->address + section->size, 0x27FFE000 - 0x1000, 0x28000000)) || + (overlaps((u32)section->address, (u32)section->address + section->size, 0x1FFFFC00, 0x20000000)) || (overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm + section->offset, (u32)firm + size))) return false; diff --git a/source/fs.c b/source/fs.c index 3c935d8..3804ab3 100644 --- a/source/fs.c +++ b/source/fs.c @@ -170,12 +170,10 @@ void loadPayload(u32 pressed, const char *payloadPath) else sprintf(absPath, "sdmc:/luma/%s", path); - char *argv[1] = {absPath}; + char *argv[2] = {absPath, (char *)fbs}; initScreens(); - if((u8 *)firm + payloadSize < (u8 *)0x23FFFE00) - memcpy((void *)0x23FFFE00, fbs, sizeof(fbs)); - launchFirm(1, argv); + launchFirm((firm->reserved2[0] & 1) ? 2 : 1, argv); } void payloadMenu(void) diff --git a/source/screen.c b/source/screen.c index 9494f6d..5e3da56 100644 --- a/source/screen.c +++ b/source/screen.c @@ -50,9 +50,9 @@ struct fb fbs[2]; static void invokeArm11Function(Arm11Operation op) { - while(*operation != NO_ARM11_OPERATION); + while(*operation != ARM11_READY); *operation = op; - while(*operation != NO_ARM11_OPERATION); + while(*operation != ARM11_READY); } void prepareArm11ForFirmlaunch(void) @@ -125,5 +125,6 @@ void initScreens(void) } clearScreens(false); + clearScreens(true); swapFramebuffers(false); } diff --git a/source/screen.h b/source/screen.h index 342db19..e369117 100644 --- a/source/screen.h +++ b/source/screen.h @@ -33,7 +33,7 @@ #define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1) -#define ARM11_PARAMETERS_ADDRESS 0x1FFFC000 +#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000 #define SCREEN_TOP_WIDTH 400 #define SCREEN_BOTTOM_WIDTH 320 @@ -45,22 +45,21 @@ struct fb { u8 *top_left; u8 *top_right; u8 *bottom; -} __attribute__((packed)); //*const fbs = (volatile struct fb *)0x23FFFE00; - -extern struct fb fbs[2]; +} __attribute__((packed)); typedef enum { - NO_ARM11_OPERATION = 0, - INIT_SCREENS_SEQUENCE, + INIT_SCREENS_SEQUENCE = 0, SETUP_FRAMEBUFFERS, CLEAR_SCREENS, SWAP_FRAMEBUFFERS, UPDATE_BRIGHTNESS, DEINIT_SCREENS, PREPARE_ARM11_FOR_FIRMLAUNCH, + ARM11_READY, } Arm11Operation; +extern struct fb fbs[2]; extern CfgData configData; void prepareArm11ForFirmlaunch(void);