Remove A9LH & Brahma support altogether, use FIRM format instead
This commit is contained in:
parent
1d4245e582
commit
ab14e77b50
13
Makefile
13
Makefile
@ -36,13 +36,13 @@ define bin2o
|
||||
endef
|
||||
|
||||
.PHONY: all
|
||||
all: a9lh
|
||||
all: firm
|
||||
|
||||
.PHONY: release
|
||||
release: $(dir_out)/$(name)$(revision).7z
|
||||
|
||||
.PHONY: a9lh
|
||||
a9lh: $(dir_out)/arm9loaderhax.bin
|
||||
.PHONY: firm
|
||||
firm: $(dir_out)/boot.firm
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
@ -63,12 +63,9 @@ $(dir_out)/$(name)$(revision).7z: all
|
||||
@mkdir -p "$(@D)"
|
||||
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py
|
||||
|
||||
$(dir_out)/arm9loaderhax.bin: $(dir_build)/main.bin
|
||||
$(dir_out)/boot.firm: $(dir_build)/main.elf
|
||||
@mkdir -p "$(@D)"
|
||||
@cp -a $(dir_build)/main.bin $@
|
||||
|
||||
$(dir_build)/main.bin: $(dir_build)/main.elf
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
@firmtool build $@ -e 0 -D $^ -C NDMA
|
||||
|
||||
$(dir_build)/main.elf: $(bundled) $(objects)
|
||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
||||
|
@ -28,7 +28,6 @@ enum singleOptions
|
||||
AUTOBOOTEMU = 0,
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
USECUSTOMPATH,
|
||||
PATCHGAMES,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
|
@ -22,15 +22,20 @@
|
||||
|
||||
#include "memory.h"
|
||||
#include "cache.h"
|
||||
#include "firm.h"
|
||||
|
||||
void main(u32 payloadSize)
|
||||
void main(int argc __attribute__((unused)), char **argv)
|
||||
{
|
||||
void *payloadAddress = (void *)0x23F00000;
|
||||
Firm *firm = (Firm *)0x24000000;
|
||||
char absPath[92];
|
||||
|
||||
memcpy(payloadAddress, (void *)0x24000000, payloadSize);
|
||||
u32 i;
|
||||
for(i = 0; i < 91 && argv[1] != 0; i++)
|
||||
absPath[i] = argv[1][i];
|
||||
for(; i < 91; i++)
|
||||
absPath[i] = 0;
|
||||
|
||||
//Ensure that all memory transfers have completed and that the caches have been flushed
|
||||
flushCaches();
|
||||
char *argvPassed[1] = {absPath};
|
||||
|
||||
((void (*)())payloadAddress)();
|
||||
launchFirm(firm, 1, argvPassed);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
@ This file is part of Luma3DS
|
||||
@ Copyright (C) 2016 Aurora Wright, TuxSH
|
||||
@ Copyright (C) 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
|
||||
|
@ -45,4 +45,4 @@
|
||||
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
|
||||
.close
|
||||
|
@ -102,4 +102,4 @@
|
||||
b die
|
||||
|
||||
.pool
|
||||
.close
|
||||
.close
|
||||
|
145
patches/reboot.s
145
patches/reboot.s
@ -2,9 +2,15 @@
|
||||
|
||||
.arm.little
|
||||
|
||||
payload_addr equ 0x23F00000 ; Brahma payload address
|
||||
payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeBrah supports)
|
||||
argv_addr equ 0x27FFDF00
|
||||
fname_addr equ 0x27FFDF80
|
||||
low_tid_addr equ 0x27FFDFE0
|
||||
copy_launch_stub_addr equ 0x27FFE000
|
||||
|
||||
firm_addr equ 0x24000000
|
||||
firm_maxsize equ (copy_launch_stub_addr - 0x1000 - firm_addr)
|
||||
|
||||
arm11_entrypoint_addr equ 0x1FFFFFFC
|
||||
.create "build/reboot.bin", 0
|
||||
.arm
|
||||
; Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||
@ -28,42 +34,41 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
|
||||
cmp r0, r2
|
||||
bne pxi_wait_recv
|
||||
|
||||
mov r4, #2
|
||||
; 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
|
||||
|
||||
open_payload:
|
||||
; Open file
|
||||
add r0, r7, #8
|
||||
adr r1, fname
|
||||
mov r2, #1
|
||||
ldr r6, [fopen]
|
||||
orr r6, 1
|
||||
blx r6
|
||||
cmp r0, #0
|
||||
beq read_payload
|
||||
subs r4, r4, #1
|
||||
beq panic
|
||||
adr r0, fname
|
||||
adr r1, nand_mount
|
||||
mov r2, #8
|
||||
bl memcpy16
|
||||
b open_payload
|
||||
|
||||
read_payload:
|
||||
; Read file
|
||||
mov r0, r7
|
||||
adr r1, bytes_read
|
||||
ldr r2, =payload_addr
|
||||
ldr r3, =payload_maxsize
|
||||
ldr r6, [r7]
|
||||
ldr r6, [r6, #0x28]
|
||||
blx r6
|
||||
; 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 to the 5th byte of the payload
|
||||
ldr r0, =payload_addr + 4
|
||||
ldr r0, =low_tid_addr
|
||||
add r1, r8, #0x1A
|
||||
mov r2, #0x10
|
||||
bl memcpy16
|
||||
|
||||
ldr r0, =fname_addr
|
||||
adr r1, fname
|
||||
mov r2, #42
|
||||
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
|
||||
@ -81,12 +86,14 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
|
||||
b die
|
||||
|
||||
memcpy16:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
add r2, r0, r2
|
||||
copy_loop:
|
||||
copy_loop16:
|
||||
ldrh r3, [r1], #2
|
||||
strh r3, [r0], #2
|
||||
cmp r0, r2
|
||||
blo copy_loop
|
||||
blo copy_loop16
|
||||
bx lr
|
||||
|
||||
panic:
|
||||
@ -98,7 +105,7 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
|
||||
bytes_read: .word 0
|
||||
fopen: .ascii "OPEN"
|
||||
.pool
|
||||
fname: .dcw "sdmc:/arm9loaderhax.bin"
|
||||
fname: .dcw "sdmc:/arm9loaderha.firm"
|
||||
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
.pool
|
||||
nand_mount: .dcw "nand"
|
||||
@ -106,12 +113,75 @@ nand_mount: .dcw "nand"
|
||||
.align 4
|
||||
kernelcode_start:
|
||||
|
||||
ldr sp, =0x080FF000
|
||||
mrs r0, cpsr ; disable interrupts
|
||||
orr r0, #0xC0
|
||||
msr cpsr, r0
|
||||
|
||||
ldr sp, =0x27FFDF00
|
||||
|
||||
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}
|
||||
mov r0, r7
|
||||
add r1, r4, r6
|
||||
mov r2, r8
|
||||
bl memcpy32
|
||||
add r5, #1
|
||||
cmp r5, #3
|
||||
blo load_section_loop
|
||||
|
||||
ldr r0, =arm11_entrypoint_addr
|
||||
ldr r1, [r4, #0x08]
|
||||
str r1, [r0]
|
||||
|
||||
mov r0, #2 ; argc
|
||||
ldr r1, =argv_addr ; argv
|
||||
ldr r2, =0xBEEF ; magic word
|
||||
|
||||
ldr r5, =arm11_entrypoint_addr
|
||||
ldr r6, [r4, #0x08]
|
||||
str r6, [r5]
|
||||
|
||||
ldr lr, [r4, #0x0c]
|
||||
bx lr
|
||||
|
||||
memcpy32:
|
||||
cmp r2, #0
|
||||
bxeq lr
|
||||
add r2, r0, r2
|
||||
copy_loop32:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
cmp r0, r2
|
||||
blo copy_loop32
|
||||
bx lr
|
||||
|
||||
copy_launch_stub_end:
|
||||
|
||||
flushCaches:
|
||||
|
||||
; Clean and flush data cache
|
||||
mov r1, #0 ; segment counter
|
||||
outer_loop:
|
||||
@ -134,10 +204,7 @@ nand_mount: .dcw "nand"
|
||||
; Flush instruction cache
|
||||
mcr p15, 0, r1, c7, c5, 0
|
||||
|
||||
; Jump to payload
|
||||
ldr r0, =payload_addr
|
||||
bx r0
|
||||
bx lr
|
||||
|
||||
.pool
|
||||
.close
|
||||
|
||||
|
@ -45,4 +45,4 @@ infoStart:
|
||||
.word 0 ; truncated commit hash
|
||||
.word 0 ; config
|
||||
infoEnd:
|
||||
.close
|
||||
.close
|
||||
|
@ -24,6 +24,8 @@
|
||||
* Adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 address;
|
||||
@ -139,7 +141,7 @@ typedef struct __attribute__((packed))
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
u32 magic;
|
||||
char magic[4];
|
||||
u32 reserved1;
|
||||
u8 *arm11Entry;
|
||||
u8 *arm9Entry;
|
||||
@ -158,4 +160,4 @@ typedef struct __attribute__((packed))
|
||||
char magic[4];
|
||||
u8 reserved2[0xC];
|
||||
u8 slot0x16keyX[0x10];
|
||||
} Arm9Bin;
|
||||
} Arm9Bin;
|
||||
|
@ -84,7 +84,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
|
||||
const char *singleOptionsText[] = { "( ) Autoboot EmuNAND",
|
||||
"( ) Use EmuNAND FIRM if booting with R",
|
||||
"( ) Enable loading external FIRMs and modules",
|
||||
"( ) Use custom path",
|
||||
"( ) Enable game patching",
|
||||
"( ) Show NAND or user string in System Settings",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
@ -147,10 +146,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
|
||||
"This isn't needed in most cases.\n\n"
|
||||
"Refer to the wiki for instructions.",
|
||||
|
||||
"Use a custom path for the\n"
|
||||
"Luma3DS payload.\n\n"
|
||||
"Refer to the wiki for instructions.",
|
||||
|
||||
"Enable overriding the region and\n"
|
||||
"language configuration and the usage\n"
|
||||
"of patched code binaries,\n"
|
||||
@ -195,8 +190,8 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
|
||||
|
||||
"Enable Luma3DS's ARM9/ARM11 exception\n"
|
||||
"handlers.\n"
|
||||
"A9LH is required, and Luma3DS should\n"
|
||||
"be ran as arm9loaderhax.bin.\n"
|
||||
"Luma3DS should be ran as:\n"
|
||||
"arm9loaderhax.bin\n\n"
|
||||
"Useful for debugging."
|
||||
};
|
||||
|
||||
@ -226,8 +221,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true },
|
||||
{ .visible = true}
|
||||
{ .visible = true }
|
||||
};
|
||||
|
||||
//Calculate the amount of the various kinds of options and pre-select the first single one
|
||||
|
@ -30,7 +30,7 @@
|
||||
|
||||
#define CONFIG_FILE "config.bin"
|
||||
#define CONFIG_VERSIONMAJOR 1
|
||||
#define CONFIG_VERSIONMINOR 10
|
||||
#define CONFIG_VERSIONMINOR 11
|
||||
|
||||
#define BOOTCFG_NAND BOOTCONFIG(0, 7)
|
||||
#define BOOTCFG_FIRM BOOTCONFIG(3, 7)
|
||||
@ -50,7 +50,6 @@ enum singleOptions
|
||||
AUTOBOOTEMU = 0,
|
||||
USEEMUFIRM,
|
||||
LOADEXTFIRMSANDMODULES,
|
||||
USECUSTOMPATH,
|
||||
PATCHGAMES,
|
||||
PATCHVERSTRING,
|
||||
SHOWGBABOOT,
|
||||
|
@ -230,7 +230,7 @@ static void aes_batch(void *dst, const void *src, u32 blockCount)
|
||||
}
|
||||
}
|
||||
|
||||
static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode)
|
||||
void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode)
|
||||
{
|
||||
*REG_AESCNT = mode |
|
||||
AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
|
||||
@ -278,10 +278,8 @@ static void sha_wait_idle()
|
||||
while(*REG_SHA_CNT & 1);
|
||||
}
|
||||
|
||||
static void sha(void *res, const void *src, u32 size, u32 mode)
|
||||
void sha(void *res, const void *src, u32 size, u32 mode)
|
||||
{
|
||||
backupAndRestoreShaHash(false);
|
||||
|
||||
sha_wait_idle();
|
||||
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
||||
|
||||
@ -571,21 +569,3 @@ void computePinHash(u8 *outbuf, const u8 *inbuf)
|
||||
aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE);
|
||||
}
|
||||
|
||||
void backupAndRestoreShaHash(bool isRestore)
|
||||
{
|
||||
if(ISSIGHAX) return;
|
||||
|
||||
static bool didShaHashBackup = false;
|
||||
__attribute__((aligned(4))) static u8 shaHashBackup[SHA_256_HASH_SIZE];
|
||||
|
||||
if(isRestore)
|
||||
{
|
||||
if(didShaHashBackup) memcpy((void *)REG_SHA_HASH, shaHashBackup, sizeof(shaHashBackup));
|
||||
}
|
||||
else if(!didShaHashBackup)
|
||||
{
|
||||
memcpy(shaHashBackup, (void *)REG_SHA_HASH, sizeof(shaHashBackup));
|
||||
didShaHashBackup = true;
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +107,9 @@
|
||||
extern u32 emuOffset;
|
||||
extern FirmwareSource firmSource;
|
||||
|
||||
void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode, u32 ivMode);
|
||||
void sha(void *res, const void *src, u32 size, u32 mode);
|
||||
|
||||
void ctrNandInit(void);
|
||||
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
|
||||
int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf);
|
||||
@ -114,4 +117,3 @@ bool decryptExeFs(Cxi *cxi);
|
||||
bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
|
||||
void kernel9Loader(Arm9Bin *arm9Section);
|
||||
void computePinHash(u8 *outbuf, const u8 *inbuf);
|
||||
void backupAndRestoreShaHash(bool isRestore);
|
||||
|
@ -35,8 +35,6 @@
|
||||
#include "fmt.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
static Firm *firm = (Firm *)0x24000000;
|
||||
|
||||
static inline bool loadFirmFromStorage(FirmwareType firmType)
|
||||
{
|
||||
const char *firmwareFiles[] = {
|
||||
|
@ -23,6 +23,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include "3dsheaders.h"
|
||||
|
||||
static Firm *const firm = (Firm *const)0x24000000;
|
||||
|
||||
u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
|
||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers);
|
||||
|
109
source/fs.c
109
source/fs.c
@ -32,6 +32,8 @@
|
||||
#include "config.h"
|
||||
#include "fatfs/ff.h"
|
||||
#include "buttons.h"
|
||||
#include "firm.h"
|
||||
#include "crypto.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
static FATFS sdFs,
|
||||
@ -116,12 +118,80 @@ void fileDelete(const char *path)
|
||||
f_unlink(path);
|
||||
}
|
||||
|
||||
static __attribute__((noinline)) bool overlaps(u32 as, u32 ae, u32 bs, u32 be)
|
||||
{
|
||||
if (as <= bs && bs <= ae)
|
||||
return true;
|
||||
else if (bs <= as && as <= be)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool checkFirmPayload(void)
|
||||
{
|
||||
if(memcmp(firm->magic, "FIRM", 4) != 0)
|
||||
return false;
|
||||
|
||||
if(firm->arm9Entry == NULL) //allow for the arm11 entrypoint to be zero in which case nothing is done on the arm11 side
|
||||
return false;
|
||||
|
||||
u32 size = 0x200;
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
size += firm->section[i].size;
|
||||
|
||||
bool arm9EpFound = false, arm11EpFound = false;
|
||||
for(u32 i = 0; i < 4; i++)
|
||||
{
|
||||
__attribute__((aligned(4))) u8 hash[0x20];
|
||||
|
||||
FirmSection *section = &firm->section[i];
|
||||
|
||||
// allow empty sections
|
||||
if (section->size == 0)
|
||||
continue;
|
||||
|
||||
if(section->offset < 0x200)
|
||||
return false;
|
||||
|
||||
if(section->address + section->size < section->address) //overflow check
|
||||
return false;
|
||||
|
||||
if(((u32)section->address & 3) || (section->offset & 0x1FF) || (section->size & 0x1FF)) //alignment check
|
||||
return false;
|
||||
|
||||
if(overlaps((u32)section->address, (u32)section->address + section->size, 0x27FFE000, 0x28000000))
|
||||
return false;
|
||||
else if(overlaps((u32)section->address, (u32)section->address + section->size, 0x27FFE000 - 0x1000, 0x27FFE000))
|
||||
return false;
|
||||
else if(overlaps((u32)section->address, (u32)section->address + section->size, (u32)firm, (u32)firm + size))
|
||||
return false;
|
||||
|
||||
sha(hash, (u8 *)firm + section->offset, section->size, SHA_256_MODE);
|
||||
if(memcmp(hash, section->hash, 0x20) != 0)
|
||||
return false;
|
||||
|
||||
if(firm->arm9Entry >= section->address && firm->arm9Entry < (section->address + section->size))
|
||||
arm9EpFound = true;
|
||||
|
||||
if(firm->arm11Entry >= section->address && firm->arm11Entry < (section->address + section->size))
|
||||
arm11EpFound = true;
|
||||
}
|
||||
|
||||
return arm9EpFound && (firm->arm11Entry == NULL || arm11EpFound);
|
||||
}
|
||||
|
||||
void loadPayload(u32 pressed, const char *payloadPath)
|
||||
{
|
||||
u32 *loaderAddress = (u32 *)0x27FFE000;
|
||||
u8 *payloadAddress = (u8 *)0x24000000;
|
||||
u32 payloadSize = 0,
|
||||
maxPayloadSize = 0xFFE00;
|
||||
maxPayloadSize = (u32)((u8 *)loaderAddress - (u8 *)firm);
|
||||
|
||||
char path[62] = {0},
|
||||
absPath[92] = {0};
|
||||
|
||||
char mountPoint[5] = {0};
|
||||
for(u32 i = 0; i < 4 && launchedPath[i] != ':'; i++)
|
||||
mountPoint[i] = launchedPath[i];
|
||||
|
||||
if(payloadPath == NULL)
|
||||
{
|
||||
@ -142,7 +212,6 @@ void loadPayload(u32 pressed, const char *payloadPath)
|
||||
DIR dir;
|
||||
FILINFO info;
|
||||
FRESULT result;
|
||||
char path[22];
|
||||
|
||||
result = f_findfirst(&dir, &info, "payloads", pattern);
|
||||
|
||||
@ -153,24 +222,36 @@ void loadPayload(u32 pressed, const char *payloadPath)
|
||||
if(!info.fname[0]) return;
|
||||
|
||||
sprintf(path, "payloads/%s", info.altname);
|
||||
payloadSize = fileRead(payloadAddress, path, maxPayloadSize);
|
||||
}
|
||||
else payloadSize = fileRead(payloadAddress, payloadPath, maxPayloadSize);
|
||||
if(memcmp(mountPoint, "nand", 4))
|
||||
sprintf(absPath, "nand:/rw/luma/payloads/%s", info.altname);
|
||||
else
|
||||
sprintf(absPath, "%s:/luma/payloads/%s", mountPoint, info.altname);
|
||||
|
||||
if(!payloadSize) return;
|
||||
payloadSize = fileRead(firm, path, maxPayloadSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(memcmp(mountPoint, "nand", 4))
|
||||
sprintf(absPath, "nand:/rw/luma/payloads/%s", payloadPath);
|
||||
else
|
||||
sprintf(absPath, "%s:/luma/payloads/%s", mountPoint, payloadPath);
|
||||
|
||||
payloadSize = fileRead(firm, payloadPath, maxPayloadSize);
|
||||
}
|
||||
|
||||
if(!payloadSize || !checkFirmPayload()) return;
|
||||
|
||||
writeConfig(true);
|
||||
|
||||
char *argv[1] = {absPath};
|
||||
memcpy(loaderAddress, loader_bin, loader_bin_size);
|
||||
|
||||
if(ISN3DS) kernel9Loader(NULL);
|
||||
backupAndRestoreShaHash(true);
|
||||
initScreens();
|
||||
|
||||
flushDCacheRange(loaderAddress, loader_bin_size);
|
||||
flushICacheRange(loaderAddress, loader_bin_size);
|
||||
|
||||
((void (*)(u32))loaderAddress)(payloadSize);
|
||||
((void (*)(int, char **, u32))loaderAddress)(1, argv, 0x0000BEEF);
|
||||
}
|
||||
|
||||
void payloadMenu(void)
|
||||
@ -190,11 +271,11 @@ void payloadMenu(void)
|
||||
|
||||
u32 nameLength = strlen(info.fname);
|
||||
|
||||
if(nameLength < 5 || nameLength > 52) continue;
|
||||
if(nameLength < 6 || nameLength > 52) continue;
|
||||
|
||||
nameLength -= 4;
|
||||
nameLength -= 5;
|
||||
|
||||
if(memcmp(info.fname + nameLength, ".bin", 4) != 0) continue;
|
||||
if(memcmp(info.fname + nameLength, ".firm", 5) != 0) continue;
|
||||
|
||||
memcpy(payloadList[payloadNum], info.fname, nameLength);
|
||||
payloadList[payloadNum][nameLength] = 0;
|
||||
@ -258,7 +339,7 @@ void payloadMenu(void)
|
||||
|
||||
if(pressed != BUTTON_START)
|
||||
{
|
||||
sprintf(path, "payloads/%s.bin", payloadList[selectedPayload]);
|
||||
sprintf(path, "payloads/%s.firm", payloadList[selectedPayload]);
|
||||
loadPayload(0, path);
|
||||
error("The payload is too large or corrupted.");
|
||||
}
|
||||
|
@ -32,12 +32,16 @@
|
||||
#include "pin.h"
|
||||
#include "crypto.h"
|
||||
#include "fmt.h"
|
||||
#include "memory.h"
|
||||
|
||||
extern CfgData configData;
|
||||
extern ConfigurationStatus needConfig;
|
||||
extern FirmwareSource firmSource;
|
||||
|
||||
void main(void)
|
||||
u16 launchedFirmTidLow[8];
|
||||
u16 launchedPath[42];
|
||||
|
||||
void main(int argc, char **argv)
|
||||
{
|
||||
bool isSafeMode = false,
|
||||
isNoForceFlagSet = false;
|
||||
@ -45,15 +49,59 @@ void main(void)
|
||||
FirmwareType firmType;
|
||||
FirmwareSource nandType;
|
||||
|
||||
switch(argc)
|
||||
{
|
||||
case 0:
|
||||
error("Unsupported launcher.");
|
||||
break;
|
||||
|
||||
case 1: //Normal boot
|
||||
{
|
||||
u32 i;
|
||||
for(i = 0; i < 41 && launchedPath[i] != 0; i++) //Copy and convert the path to utf16
|
||||
launchedPath[2 * i] = argv[0][i];
|
||||
for(; i < 41; i++)
|
||||
launchedPath[i] = 0;
|
||||
|
||||
for(u32 i = 0; i < 8; i++)
|
||||
launchedFirmTidLow[i] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: //Firmlaunch
|
||||
{
|
||||
u32 i;
|
||||
u16 *p = (u16 *)argv[0];
|
||||
for(i = 0; i < 41 && launchedPath[i] != 0; i++)
|
||||
launchedPath[i] = p[i];
|
||||
for(; i < 41; i++)
|
||||
launchedPath[i] = 0;
|
||||
|
||||
memcpy(launchedFirmTidLow, (u16 *)argv[1], 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char mountPoint[5] = {0};
|
||||
for(u32 i = 0; i < 4 && argv[0][i] != ':'; i++)
|
||||
mountPoint[i] = argv[0][i];
|
||||
|
||||
//Mount SD or CTRNAND
|
||||
bool isSdMode;
|
||||
if(mountFs(true, false)) isSdMode = true;
|
||||
else
|
||||
|
||||
if(memcmp(mountPoint, "sdmc", 4) == 0)
|
||||
{
|
||||
if(!mountFs(true, false)) error("Failed to mount SD.");
|
||||
isSdMode = true;
|
||||
}
|
||||
else if(memcmp(mountPoint, "nand", 4) == 0)
|
||||
{
|
||||
firmSource = FIRMWARE_SYSNAND;
|
||||
if(!mountFs(false, true)) error("Failed to mount SD and CTRNAND.");
|
||||
isSdMode = false;
|
||||
}
|
||||
else
|
||||
error("Launched from an unsupported location");
|
||||
|
||||
//Attempt to read the configuration file
|
||||
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||
|
@ -37,30 +37,6 @@
|
||||
#include "utils.h"
|
||||
#include "../build/bundled.h"
|
||||
|
||||
static inline void pathChanger(u8 *pos)
|
||||
{
|
||||
const char *pathFile = "path.txt";
|
||||
u8 path[57];
|
||||
|
||||
u32 pathSize = fileRead(path, pathFile, sizeof(path));
|
||||
|
||||
if(pathSize < 6) return;
|
||||
|
||||
if(path[pathSize - 1] == 0xA) pathSize--;
|
||||
if(path[pathSize - 1] == 0xD) pathSize--;
|
||||
|
||||
if(pathSize < 6 || pathSize > 55 || path[0] != '/' || memcmp(path + pathSize - 4, ".bin", 4) != 0) return;
|
||||
|
||||
u16 finalPath[56];
|
||||
for(u32 i = 0; i < pathSize; i++)
|
||||
finalPath[i] = (u16)path[i];
|
||||
|
||||
finalPath[pathSize] = 0;
|
||||
|
||||
u8 *posPath = memsearch(pos, u"sd", reboot_bin_size, 4) + 0xA;
|
||||
memcpy(posPath, finalPath, (pathSize + 1) * 2);
|
||||
}
|
||||
|
||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||
{
|
||||
u8 *temp = memsearch(pos, "NCCH", size, 4);
|
||||
@ -159,7 +135,8 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||
u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
|
||||
*pos_fopen = fOpenOffset;
|
||||
|
||||
if(CONFIG(USECUSTOMPATH)) pathChanger(off);
|
||||
//u16 *fname = (u16 *)memsearch(off, u"sd", reboot_bin_size, 4);
|
||||
//memcpy(fname, u"sdmc:/test.firm", 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,32 +24,31 @@
|
||||
.align 4
|
||||
.global _start
|
||||
_start:
|
||||
b start
|
||||
|
||||
.global launchedFirmTidLow
|
||||
launchedFirmTidLow:
|
||||
.hword 0, 0, 0, 0, 0, 0, 0, 0
|
||||
|
||||
start:
|
||||
@ Disable interrupts
|
||||
mrs r0, cpsr
|
||||
orr r0, #0x1C0
|
||||
msr cpsr_cx, r0
|
||||
mrs r4, cpsr
|
||||
orr r4, #0x1C0
|
||||
msr cpsr_cx, r4
|
||||
|
||||
ldr r4, =0xBEEF
|
||||
cmp r2, r4
|
||||
movne r0, #0 @ check magic word
|
||||
|
||||
@ Change the stack pointer
|
||||
mov sp, #0x27000000
|
||||
|
||||
@ 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
|
||||
mrc p15, 0, r4, c1, c0, 0 @ read control register
|
||||
bic r4, #(1<<12) @ - instruction cache disable
|
||||
bic r4, #(1<<2) @ - data cache disable
|
||||
bic r4, #(1<<0) @ - mpu disable
|
||||
mcr p15, 0, r4, c1, c0, 0 @ write control register
|
||||
|
||||
@ Flush caches
|
||||
bl flushEntireDCache
|
||||
bl flushEntireICache
|
||||
|
||||
push {r0-r3}
|
||||
|
||||
@ Give read/write access to all the memory regions
|
||||
ldr r0, =0x3333333
|
||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||
@ -98,4 +97,5 @@ start:
|
||||
sub r2, r0
|
||||
bl memset32
|
||||
|
||||
pop {r0-r3}
|
||||
b main
|
||||
|
@ -115,4 +115,5 @@ typedef enum FirmwareType
|
||||
NATIVE_FIRM1X2X
|
||||
} FirmwareType;
|
||||
|
||||
extern u16 launchedFirmTidLow[8]; //Defined in start.s
|
||||
extern u16 launchedFirmTidLow[8];
|
||||
extern u16 launchedPath[42];
|
||||
|
Reference in New Issue
Block a user