Do the same for large patches (emunand, reboot). This greatly simplifies logic.
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
#include "memory.h"
|
||||
#include "utils.h"
|
||||
#include "fatfs/sdmmc/sdmmc.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "large_patches.h"
|
||||
|
||||
u32 emuOffset,
|
||||
emuHeader;
|
||||
@@ -109,8 +109,8 @@ static inline bool getFreeK9Space(u8 *pos, u32 size, u8 **freeK9Space)
|
||||
//Looking for the last free space before Process9
|
||||
*freeK9Space = memsearch(pos, pattern, size, sizeof(pattern));
|
||||
|
||||
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunand_bin_size ||
|
||||
*(u32 *)(*freeK9Space + 0x455 + emunand_bin_size - 4) != 0xFFFFFFFF) return false;
|
||||
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunandPatchSize ||
|
||||
*(u32 *)(*freeK9Space + 0x455 + emunandPatchSize - 4) != 0xFFFFFFFF) return false;
|
||||
|
||||
*freeK9Space += 0x455;
|
||||
|
||||
@@ -195,20 +195,17 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
|
||||
|
||||
u32 ret = 0;
|
||||
|
||||
//Copy EmuNAND code
|
||||
memcpy(freeK9Space, emunand_bin, emunand_bin_size);
|
||||
|
||||
//Add the data of the found EmuNAND
|
||||
u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_bin_size, 4),
|
||||
*posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_bin_size, 4);
|
||||
*posOffset = emuOffset;
|
||||
*posHeader = emuHeader;
|
||||
emunandPatchNandOffset = emuOffset;
|
||||
emunandPatchNcsdHeaderOffset = emuHeader;
|
||||
|
||||
//Find and add the SDMMC struct
|
||||
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
|
||||
u32 sdmmc;
|
||||
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
|
||||
if(!ret) *posSdmmc = sdmmc;
|
||||
if(!ret) emunandPatchSdmmcStructPtr = sdmmc;
|
||||
|
||||
//Copy EmuNAND code
|
||||
memcpy(freeK9Space, emunandPatch, emunandPatchSize);
|
||||
|
||||
//Add EmuNAND hooks
|
||||
u32 branchOffset = (u32)(freeK9Space - arm9Section + kernel9Address);
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "screen.h"
|
||||
#include "fmt.h"
|
||||
#include "chainloader.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
static Firm *firm = (Firm *)0x20001000;
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
#include "buttons.h"
|
||||
#include "firm.h"
|
||||
#include "crypto.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
static FATFS sdFs,
|
||||
nandFs;
|
||||
|
||||
38
source/large_patches.h
Normal file
38
source/large_patches.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of Luma3DS
|
||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Additional Terms 7.b and 7.c of GPLv3 apply 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.
|
||||
* * Prohibiting misrepresentation of the origin of that material,
|
||||
* or requiring that modified versions of such material be marked in
|
||||
* reasonable ways as different from the original version.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
extern const u8 emunandPatch[];
|
||||
extern const u32 emunandPatchSize;
|
||||
extern u32 emunandPatchSdmmcStructPtr, emunandPatchNandOffset, emunandPatchNcsdHeaderOffset;
|
||||
|
||||
extern const u8 rebootPatch[];
|
||||
extern const u32 rebootPatchSize;
|
||||
extern u32 rebootPatchFopenPtr;
|
||||
extern u16 rebootPatchFileName[80+1];
|
||||
291
source/large_patches.s
Normal file
291
source/large_patches.s
Normal file
@@ -0,0 +1,291 @@
|
||||
.section .large_patch.emunand, "aw", %progbits
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
@ Code originally by Normmatt
|
||||
|
||||
.global emunandPatch
|
||||
emunandPatch:
|
||||
@ Original code that still needs to be executed
|
||||
mov r4, r0
|
||||
mov r5, r1
|
||||
mov r7, r2
|
||||
mov r6, r3
|
||||
@ End
|
||||
|
||||
@ If we're already trying to access the SD, return
|
||||
ldr r2, [r0, #4]
|
||||
ldr r1, emunandPatchSdmmcStructPtr
|
||||
cmp r2, r1
|
||||
beq out
|
||||
|
||||
str r1, [r0, #4] @ Set object to be SD
|
||||
ldr r2, [r0, #8] @ Get sector to read
|
||||
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
||||
|
||||
ldr r3, emunandPatchNandOffset
|
||||
add r2, r3 @ Add the offset to the NAND in the SD
|
||||
|
||||
ldreq r3, emunandPatchNcsdHeaderOffset
|
||||
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
||||
|
||||
str r2, [r0, #8] @ Store sector to read
|
||||
|
||||
out:
|
||||
@ Restore registers.
|
||||
mov r1, r5
|
||||
mov r2, r7
|
||||
mov r3, r6
|
||||
|
||||
@ Return 4 bytes behind where we got called,
|
||||
@ due to the offset of this function being stored there
|
||||
mov r0, lr
|
||||
add r0, #4
|
||||
bx r0
|
||||
|
||||
.pool
|
||||
|
||||
.global emunandPatchSdmmcStructPtr
|
||||
.global emunandPatchNandOffset
|
||||
.global emunandPatchNcsdHeaderOffset
|
||||
|
||||
emunandPatchSdmmcStructPtr: .word 0 @ Pointer to sdmmc struct
|
||||
emunandPatchNandOffset: .word 0 @ For rednand this should be 1
|
||||
emunandPatchNcsdHeaderOffset: .word 0 @ Depends on nand manufacturer + emunand type (GW/RED)
|
||||
|
||||
.pool
|
||||
.balign 4
|
||||
|
||||
_emunandPatchEnd:
|
||||
|
||||
.global emunandPatchSize
|
||||
emunandPatchSize:
|
||||
.word _emunandPatchEnd - emunandPatch
|
||||
|
||||
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
|
||||
@ Code originally from delebile and mid-kid
|
||||
|
||||
.section .large_patch.reboot, "aw", %progbits
|
||||
.arm
|
||||
.align 4
|
||||
|
||||
.set copy_launch_stub_stack_top, 0x01FFB800
|
||||
.set copy_launch_stub_stack_bottom, 0x01FFA800
|
||||
.set copy_launch_stub_addr, 0x01FF9000
|
||||
|
||||
.set argv_addr, (copy_launch_stub_stack_bottom - 0x100)
|
||||
.set fname_addr, (copy_launch_stub_stack_bottom - 0x200)
|
||||
.set low_tid_addr, (copy_launch_stub_stack_bottom - 0x300)
|
||||
|
||||
.set firm_addr, 0x20001000
|
||||
.set firm_maxsize, 0x07FFF000
|
||||
|
||||
.global rebootPatch
|
||||
rebootPatch:
|
||||
@ Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||
@ - r1: FIRM path in exefs.
|
||||
@ - r7 (or r8): pointer to file object
|
||||
@ - *r7: vtable
|
||||
@ - *(vtable + 0x28): fread function
|
||||
@ - *(r7 + 8): file handle
|
||||
|
||||
sub r7, r0, #8
|
||||
mov r8, r1
|
||||
|
||||
pxi_wait_recv:
|
||||
ldr r2, =0x44846
|
||||
ldr r0, =0x10008000
|
||||
readPxiLoop1:
|
||||
ldrh r1, [r0, #4]
|
||||
lsls r1, #0x17
|
||||
bmi readPxiLoop1
|
||||
ldr r0, [r0, #0xC]
|
||||
cmp r0, r2
|
||||
bne pxi_wait_recv
|
||||
|
||||
@ Open file
|
||||
add r0, r7, #8
|
||||
adr r1, rebootPatchFileName
|
||||
mov r2, #1
|
||||
adr r6, rebootPatchFopenPtr
|
||||
ldr r6, [r6]
|
||||
orr r6, #1
|
||||
blx r6
|
||||
cmp r0, #0
|
||||
bne panic
|
||||
|
||||
@ Read file
|
||||
mov r0, r7
|
||||
adr r1, bytes_read
|
||||
ldr r2, =firm_addr
|
||||
ldr r3, =firm_maxsize
|
||||
ldr r6, [r7]
|
||||
ldr r6, [r6, #0x28]
|
||||
blx r6
|
||||
|
||||
@ Copy the low TID (in UTF-16) of the wanted firm
|
||||
ldr r0, =low_tid_addr
|
||||
add r1, r8, #0x1A
|
||||
mov r2, #0x10
|
||||
bl memcpy16
|
||||
|
||||
@ Copy argv[0]
|
||||
ldr r0, =fname_addr
|
||||
adr r1, rebootPatchFileName
|
||||
mov r2, #82
|
||||
bl memcpy16
|
||||
|
||||
ldr r0, =argv_addr
|
||||
ldr r1, =fname_addr
|
||||
ldr r2, =low_tid_addr
|
||||
stmia r0, {r1, r2}
|
||||
|
||||
@ Set kernel state
|
||||
mov r0, #0
|
||||
mov r1, #0
|
||||
mov r2, #0
|
||||
mov r3, #0
|
||||
swi 0x7C
|
||||
|
||||
goto_reboot:
|
||||
@ Jump to reboot code
|
||||
ldr r0, kernel_func_displ
|
||||
add r0, pc @ pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
|
||||
swi 0x7B
|
||||
|
||||
die:
|
||||
b die
|
||||
|
||||
memcpy16:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
add r2, r0, r2
|
||||
copy_loop16:
|
||||
ldrh r3, [r1], #2
|
||||
strh r3, [r0], #2
|
||||
cmp r0, r2
|
||||
blo copy_loop16
|
||||
bx lr
|
||||
|
||||
panic:
|
||||
mov r1, r0 @ unused register
|
||||
mov r0, #0
|
||||
swi 0x3C @ svcBreak(USERBREAK_PANIC)
|
||||
b die
|
||||
|
||||
kernel_func_displ:
|
||||
.word kernelcode_start - goto_reboot - 12
|
||||
|
||||
bytes_read:
|
||||
.word 0
|
||||
|
||||
.global rebootPatchFopenPtr
|
||||
rebootPatchFopenPtr:
|
||||
.word 0
|
||||
|
||||
.pool
|
||||
|
||||
.global rebootPatchFileName
|
||||
rebootPatchFileName:
|
||||
.skip 2*(80+1)
|
||||
|
||||
.balign 4
|
||||
kernelcode_start:
|
||||
|
||||
msr cpsr_cxsf, #0xD3 @ disable interrupts and clear flags
|
||||
|
||||
ldr sp, =copy_launch_stub_stack_top
|
||||
|
||||
ldr r0, =copy_launch_stub_addr
|
||||
adr r1, copy_launch_stub
|
||||
mov r2, #(copy_launch_stub_end - copy_launch_stub)
|
||||
bl memcpy32
|
||||
|
||||
@ Disable MPU
|
||||
ldr r0, =0x42078 @ alt vector select, enable itcm
|
||||
mcr p15, 0, r0, c1, c0, 0
|
||||
|
||||
bl flushCaches
|
||||
|
||||
ldr r0, =copy_launch_stub_addr
|
||||
bx r0
|
||||
|
||||
copy_launch_stub:
|
||||
|
||||
ldr r4, =firm_addr
|
||||
|
||||
mov r5, #0
|
||||
load_section_loop:
|
||||
@ Such checks. Very ghetto. Wow.
|
||||
add r3, r4, #0x40
|
||||
add r3, r5,lsl #5
|
||||
add r3, r5,lsl #4
|
||||
ldmia r3, {r6-r8}
|
||||
cmp r8, #0
|
||||
movne r0, r7
|
||||
addne r1, r4, r6
|
||||
movne r2, r8
|
||||
blne memcpy32
|
||||
add r5, #1
|
||||
cmp r5, #4
|
||||
blo load_section_loop
|
||||
|
||||
mov r0, #2 @ argc
|
||||
ldr r1, =argv_addr @ argv
|
||||
ldr r2, =0xBABE @ magic word
|
||||
|
||||
mov r5, #0x20000000
|
||||
ldr r6, [r4, #0x08]
|
||||
str r6, [r5, #-4] @ store arm11 entrypoint
|
||||
|
||||
ldr lr, [r4, #0x0c]
|
||||
bx lr
|
||||
|
||||
memcpy32:
|
||||
add r2, r0, r2
|
||||
copy_loop32:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
cmp r0, r2
|
||||
blo copy_loop32
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
|
||||
copy_launch_stub_end:
|
||||
|
||||
flushCaches:
|
||||
|
||||
@ Clean and flush data cache
|
||||
mov r1, #0 @ segment counter
|
||||
outer_loop:
|
||||
mov r0, #0 @ line counter
|
||||
|
||||
inner_loop:
|
||||
orr r2, r1, r0 @ generate segment and line address
|
||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||
add r0, #0x20 @ increment to next line
|
||||
cmp r0, #0x400
|
||||
bne inner_loop
|
||||
|
||||
add r1, #0x40000000
|
||||
cmp r1, #0
|
||||
bne outer_loop
|
||||
|
||||
@ Drain write buffer
|
||||
mcr p15, 0, r1, c7, c10, 4
|
||||
|
||||
@ Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
.balign 4
|
||||
|
||||
_rebootPatchEnd:
|
||||
|
||||
.global rebootPatchSize
|
||||
rebootPatchSize:
|
||||
.word _rebootPatchEnd - rebootPatch
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "config.h"
|
||||
#include "utils.h"
|
||||
#include "arm9_exception_handlers.h"
|
||||
#include "../build/bundled.h"
|
||||
#include "large_patches.h"
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
@@ -316,15 +316,14 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
||||
|
||||
//Copy firmlaunch code
|
||||
memcpy(off, reboot_bin, reboot_bin_size);
|
||||
|
||||
//Put the fOpen offset in the right location
|
||||
u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
|
||||
*pos_fopen = fOpenOffset;
|
||||
rebootPatchFopenPtr = fOpenOffset;
|
||||
|
||||
u16 *fname = (u16 *)memsearch(off, "FILE", reboot_bin_size, 8);
|
||||
memcpy(fname, launchedPath, 2 * (1 + pathLen));
|
||||
//Copy the launched path
|
||||
memcpy(rebootPatchFileName, launchedPath, 2 * (1 + pathLen));
|
||||
|
||||
//Copy firmlaunch code
|
||||
memcpy(off, rebootPatch, rebootPatchSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user