From 0c9365bcb7eeb8ea05bb0976df750266dd4b91fb Mon Sep 17 00:00:00 2001 From: TuxSH Date: Tue, 22 May 2018 22:55:04 +0200 Subject: [PATCH] Do the same for large patches (emunand, reboot). This greatly simplifies logic. --- Makefile | 17 +-- linker.ld | 1 + patches/emunand.s | 48 ------- patches/reboot.s | 207 ----------------------------- source/emunand.c | 21 ++- source/firm.c | 1 - source/fs.c | 1 - source/large_patches.h | 38 ++++++ source/large_patches.s | 291 +++++++++++++++++++++++++++++++++++++++++ source/patches.c | 15 +-- 10 files changed, 348 insertions(+), 292 deletions(-) delete mode 100644 patches/emunand.s delete mode 100644 patches/reboot.s create mode 100644 source/large_patches.h create mode 100644 source/large_patches.s diff --git a/Makefile b/Makefile index b328640..c0eadad 100644 --- a/Makefile +++ b/Makefile @@ -38,7 +38,6 @@ ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),) endif dir_source := source -dir_patches := patches dir_arm11 := arm11 dir_k11_extension := k11_extension dir_sysmodules := sysmodules @@ -57,8 +56,6 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o - modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi define bin2o @@ -110,7 +107,7 @@ $(dir_build)/arm11.elf: $(dir_arm11) @mkdir -p "$(@D)" @$(MAKE) -C $< -$(dir_build)/main.elf: $(bundled) $(objects) +$(dir_build)/main.elf: $(objects) $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ $(dir_build)/k11_extension.bin: $(dir_k11_extension) @@ -136,10 +133,6 @@ $(dir_build)/pxi.cxi: $(dir_pxi) $(dir_build)/%.bin.o: $(dir_build)/%.bin @$(bin2o) -$(dir_build)/%.bin: $(dir_patches)/%.s - @mkdir -p "$(@D)" - @armips $< - $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 $(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\"" $(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_MINOR="$(version_minor)"\ @@ -147,13 +140,7 @@ $(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_M $(dir_build)/firm.o: $(dir_build)/modules.bin $(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell wc -c $(dir_build)/modules.bin | tr -d [:space:][:alpha:][:punct:])" -$(dir_build)/bundled.h: $(bundled) - @$(foreach f, $(bundled),\ - echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\ - echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\ - ) - -$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h +$(dir_build)/%.o: $(dir_source)/%.c @mkdir -p "$(@D)" $(COMPILE.c) $(OUTPUT_OPTION) $< diff --git a/linker.ld b/linker.ld index c576f3d..117361c 100644 --- a/linker.ld +++ b/linker.ld @@ -138,6 +138,7 @@ SECTIONS { *(.data) *(.data.*) + KEEP (*(.large_patch*)) *(.gnu.linkonce.d*) CONSTRUCTORS . = ALIGN(4); diff --git a/patches/emunand.s b/patches/emunand.s deleted file mode 100644 index b0d6643..0000000 --- a/patches/emunand.s +++ /dev/null @@ -1,48 +0,0 @@ -; Code by Normmatt - -.arm.little - -.create "build/emunand.bin", 0 -.arm - ; 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, [sdmmc] - 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, [nand_offset] - add r2, r3 ; Add the offset to the NAND in the SD - - ldreq r3, [ncsd_header_offset] - 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 -sdmmc: .ascii "SDMC" -nand_offset: .ascii "NAND" ; For rednand this should be 1 -ncsd_header_offset: .ascii "NCSD" ; Depends on nand manufacturer + emunand type (GW/RED) -.close diff --git a/patches/reboot.s b/patches/reboot.s deleted file mode 100644 index 777f2ac..0000000 --- a/patches/reboot.s +++ /dev/null @@ -1,207 +0,0 @@ -; Code originally from delebile and mid-kid - -.arm.little - -copy_launch_stub_stack_top equ 0x01FFB800 -copy_launch_stub_stack_bottom equ 0x01FFA800 -copy_launch_stub_addr equ 0x01FF9000 - -argv_addr equ (copy_launch_stub_stack_bottom - 0x100) -fname_addr equ (copy_launch_stub_stack_bottom - 0x200) -low_tid_addr equ (copy_launch_stub_stack_bottom - 0x300) - -firm_addr equ 0x20001000 -firm_maxsize equ 0x07FFF000 - -.create "build/reboot.bin", 0 -.arm - ; 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, fname - mov r2, #1 - ldr r6, [fopen] - 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, fname - 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, =(kernelcode_start - goto_reboot - 12) - 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 - -bytes_read: .word 0 -fopen: .ascii "OPEN" -.pool - -.area 2*(80+1), 0 -fname: .ascii "FILE" -.endarea - -.align 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 - -.close diff --git a/source/emunand.c b/source/emunand.c index d67f41e..f9aa6e0 100644 --- a/source/emunand.c +++ b/source/emunand.c @@ -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); diff --git a/source/firm.c b/source/firm.c index 1e3ecba..053dec8 100755 --- a/source/firm.c +++ b/source/firm.c @@ -38,7 +38,6 @@ #include "screen.h" #include "fmt.h" #include "chainloader.h" -#include "../build/bundled.h" static Firm *firm = (Firm *)0x20001000; diff --git a/source/fs.c b/source/fs.c index 471beb1..f546c8a 100644 --- a/source/fs.c +++ b/source/fs.c @@ -37,7 +37,6 @@ #include "buttons.h" #include "firm.h" #include "crypto.h" -#include "../build/bundled.h" static FATFS sdFs, nandFs; diff --git a/source/large_patches.h b/source/large_patches.h new file mode 100644 index 0000000..6d99f56 --- /dev/null +++ b/source/large_patches.h @@ -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 . +* +* 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]; diff --git a/source/large_patches.s b/source/large_patches.s new file mode 100644 index 0000000..021a893 --- /dev/null +++ b/source/large_patches.s @@ -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 diff --git a/source/patches.c b/source/patches.c index d4bc75e..67c8f5d 100644 --- a/source/patches.c +++ b/source/patches.c @@ -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; }