Remove A9LH & Brahma support altogether, use FIRM format instead

This commit is contained in:
TuxSH 2017-05-18 01:05:56 +02:00
parent 1d4245e582
commit ab14e77b50
20 changed files with 307 additions and 154 deletions

View File

@ -36,13 +36,13 @@ define bin2o
endef endef
.PHONY: all .PHONY: all
all: a9lh all: firm
.PHONY: release .PHONY: release
release: $(dir_out)/$(name)$(revision).7z release: $(dir_out)/$(name)$(revision).7z
.PHONY: a9lh .PHONY: firm
a9lh: $(dir_out)/arm9loaderhax.bin firm: $(dir_out)/boot.firm
.PHONY: clean .PHONY: clean
clean: clean:
@ -63,12 +63,9 @@ $(dir_out)/$(name)$(revision).7z: all
@mkdir -p "$(@D)" @mkdir -p "$(@D)"
@7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser.py @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)" @mkdir -p "$(@D)"
@cp -a $(dir_build)/main.bin $@ @firmtool build $@ -e 0 -D $^ -C NDMA
$(dir_build)/main.bin: $(dir_build)/main.elf
$(OBJCOPY) -S -O binary $< $@
$(dir_build)/main.elf: $(bundled) $(objects) $(dir_build)/main.elf: $(bundled) $(objects)
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^

View File

@ -28,7 +28,6 @@ enum singleOptions
AUTOBOOTEMU = 0, AUTOBOOTEMU = 0,
USEEMUFIRM, USEEMUFIRM,
LOADEXTFIRMSANDMODULES, LOADEXTFIRMSANDMODULES,
USECUSTOMPATH,
PATCHGAMES, PATCHGAMES,
PATCHVERSTRING, PATCHVERSTRING,
SHOWGBABOOT, SHOWGBABOOT,

View File

@ -22,15 +22,20 @@
#include "memory.h" #include "memory.h"
#include "cache.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 char *argvPassed[1] = {absPath};
flushCaches();
((void (*)())payloadAddress)(); launchFirm(firm, 1, argvPassed);
} }

View File

@ -1,5 +1,5 @@
@ This file is part of Luma3DS @ 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 @ 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 @ it under the terms of the GNU General Public License as published by

View File

@ -2,9 +2,15 @@
.arm.little .arm.little
payload_addr equ 0x23F00000 ; Brahma payload address argv_addr equ 0x27FFDF00
payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeBrah supports) 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 .create "build/reboot.bin", 0
.arm .arm
; Interesting registers and locations to keep in mind, set just before this code is ran: ; Interesting registers and locations to keep in mind, set just before this code is ran:
@ -28,9 +34,6 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
cmp r0, r2 cmp r0, r2
bne pxi_wait_recv bne pxi_wait_recv
mov r4, #2
open_payload:
; Open file ; Open file
add r0, r7, #8 add r0, r7, #8
adr r1, fname adr r1, fname
@ -39,31 +42,33 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
orr r6, 1 orr r6, 1
blx r6 blx r6
cmp r0, #0 cmp r0, #0
beq read_payload bne panic
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 ; Read file
mov r0, r7 mov r0, r7
adr r1, bytes_read adr r1, bytes_read
ldr r2, =payload_addr ldr r2, =firm_addr
ldr r3, =payload_maxsize ldr r3, =firm_maxsize
ldr r6, [r7] ldr r6, [r7]
ldr r6, [r6, #0x28] ldr r6, [r6, #0x28]
blx r6 blx r6
; Copy the low TID (in UTF-16) of the wanted firm to the 5th byte of the payload ; 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 add r1, r8, #0x1A
mov r2, #0x10 mov r2, #0x10
bl memcpy16 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 ; Set kernel state
mov r0, #0 mov r0, #0
mov r1, #0 mov r1, #0
@ -81,12 +86,14 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
b die b die
memcpy16: memcpy16:
cmp r2, #0
bxeq lr
add r2, r0, r2 add r2, r0, r2
copy_loop: copy_loop16:
ldrh r3, [r1], #2 ldrh r3, [r1], #2
strh r3, [r0], #2 strh r3, [r0], #2
cmp r0, r2 cmp r0, r2
blo copy_loop blo copy_loop16
bx lr bx lr
panic: panic:
@ -98,7 +105,7 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
bytes_read: .word 0 bytes_read: .word 0
fopen: .ascii "OPEN" fopen: .ascii "OPEN"
.pool .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 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.pool .pool
nand_mount: .dcw "nand" nand_mount: .dcw "nand"
@ -106,12 +113,75 @@ nand_mount: .dcw "nand"
.align 4 .align 4
kernelcode_start: 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 ; Disable MPU
ldr r0, =0x42078 ; alt vector select, enable itcm ldr r0, =0x42078 ; alt vector select, enable itcm
mcr p15, 0, r0, c1, c0, 0 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 ; Clean and flush data cache
mov r1, #0 ; segment counter mov r1, #0 ; segment counter
outer_loop: outer_loop:
@ -134,10 +204,7 @@ nand_mount: .dcw "nand"
; Flush instruction cache ; Flush instruction cache
mcr p15, 0, r1, c7, c5, 0 mcr p15, 0, r1, c7, c5, 0
; Jump to payload bx lr
ldr r0, =payload_addr
bx r0
.pool .pool
.close .close

View File

@ -24,6 +24,8 @@
* Adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h * Adapted from 3DBrew and https://github.com/mid-kid/CakesForeveryWan/blob/master/source/headers.h
*/ */
#pragma once
typedef struct __attribute__((packed)) typedef struct __attribute__((packed))
{ {
u32 address; u32 address;
@ -139,7 +141,7 @@ typedef struct __attribute__((packed))
typedef struct __attribute__((packed)) typedef struct __attribute__((packed))
{ {
u32 magic; char magic[4];
u32 reserved1; u32 reserved1;
u8 *arm11Entry; u8 *arm11Entry;
u8 *arm9Entry; u8 *arm9Entry;

View File

@ -84,7 +84,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
const char *singleOptionsText[] = { "( ) Autoboot EmuNAND", const char *singleOptionsText[] = { "( ) Autoboot EmuNAND",
"( ) Use EmuNAND FIRM if booting with R", "( ) Use EmuNAND FIRM if booting with R",
"( ) Enable loading external FIRMs and modules", "( ) Enable loading external FIRMs and modules",
"( ) Use custom path",
"( ) Enable game patching", "( ) Enable game patching",
"( ) Show NAND or user string in System Settings", "( ) Show NAND or user string in System Settings",
"( ) Show GBA boot screen in patched AGB_FIRM", "( ) 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" "This isn't needed in most cases.\n\n"
"Refer to the wiki for instructions.", "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" "Enable overriding the region and\n"
"language configuration and the usage\n" "language configuration and the usage\n"
"of patched code binaries,\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" "Enable Luma3DS's ARM9/ARM11 exception\n"
"handlers.\n" "handlers.\n"
"A9LH is required, and Luma3DS should\n" "Luma3DS should be ran as:\n"
"be ran as arm9loaderhax.bin.\n" "arm9loaderhax.bin\n\n"
"Useful for debugging." "Useful for debugging."
}; };
@ -226,7 +221,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode)
{ .visible = true }, { .visible = true },
{ .visible = true }, { .visible = true },
{ .visible = true }, { .visible = true },
{ .visible = true },
{ .visible = true } { .visible = true }
}; };

View File

@ -30,7 +30,7 @@
#define CONFIG_FILE "config.bin" #define CONFIG_FILE "config.bin"
#define CONFIG_VERSIONMAJOR 1 #define CONFIG_VERSIONMAJOR 1
#define CONFIG_VERSIONMINOR 10 #define CONFIG_VERSIONMINOR 11
#define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_NAND BOOTCONFIG(0, 7)
#define BOOTCFG_FIRM BOOTCONFIG(3, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7)
@ -50,7 +50,6 @@ enum singleOptions
AUTOBOOTEMU = 0, AUTOBOOTEMU = 0,
USEEMUFIRM, USEEMUFIRM,
LOADEXTFIRMSANDMODULES, LOADEXTFIRMSANDMODULES,
USECUSTOMPATH,
PATCHGAMES, PATCHGAMES,
PATCHVERSTRING, PATCHVERSTRING,
SHOWGBABOOT, SHOWGBABOOT,

View File

@ -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 | *REG_AESCNT = mode |
AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER |
@ -278,10 +278,8 @@ static void sha_wait_idle()
while(*REG_SHA_CNT & 1); 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(); sha_wait_idle();
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND; *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); aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE); 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;
}
}

View File

@ -107,6 +107,9 @@
extern u32 emuOffset; extern u32 emuOffset;
extern FirmwareSource firmSource; 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); void ctrNandInit(void);
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
int ctrNandWrite(u32 sector, u32 sectorCount, const u8 *inbuf); 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); bool decryptNusFirm(const Ticket *ticket, Cxi *cxi, u32 ncchSize);
void kernel9Loader(Arm9Bin *arm9Section); void kernel9Loader(Arm9Bin *arm9Section);
void computePinHash(u8 *outbuf, const u8 *inbuf); void computePinHash(u8 *outbuf, const u8 *inbuf);
void backupAndRestoreShaHash(bool isRestore);

View File

@ -35,8 +35,6 @@
#include "fmt.h" #include "fmt.h"
#include "../build/bundled.h" #include "../build/bundled.h"
static Firm *firm = (Firm *)0x24000000;
static inline bool loadFirmFromStorage(FirmwareType firmType) static inline bool loadFirmFromStorage(FirmwareType firmType)
{ {
const char *firmwareFiles[] = { const char *firmwareFiles[] = {

View File

@ -23,6 +23,9 @@
#pragma once #pragma once
#include "types.h" #include "types.h"
#include "3dsheaders.h"
static Firm *const firm = (Firm *const)0x24000000;
u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode); u32 loadFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers); u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, bool isSafeMode, bool doUnitinfoPatch, bool enableExceptionHandlers);

View File

@ -32,6 +32,8 @@
#include "config.h" #include "config.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "buttons.h" #include "buttons.h"
#include "firm.h"
#include "crypto.h"
#include "../build/bundled.h" #include "../build/bundled.h"
static FATFS sdFs, static FATFS sdFs,
@ -116,12 +118,80 @@ void fileDelete(const char *path)
f_unlink(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) void loadPayload(u32 pressed, const char *payloadPath)
{ {
u32 *loaderAddress = (u32 *)0x27FFE000; u32 *loaderAddress = (u32 *)0x27FFE000;
u8 *payloadAddress = (u8 *)0x24000000;
u32 payloadSize = 0, 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) if(payloadPath == NULL)
{ {
@ -142,7 +212,6 @@ void loadPayload(u32 pressed, const char *payloadPath)
DIR dir; DIR dir;
FILINFO info; FILINFO info;
FRESULT result; FRESULT result;
char path[22];
result = f_findfirst(&dir, &info, "payloads", pattern); result = f_findfirst(&dir, &info, "payloads", pattern);
@ -153,24 +222,36 @@ void loadPayload(u32 pressed, const char *payloadPath)
if(!info.fname[0]) return; if(!info.fname[0]) return;
sprintf(path, "payloads/%s", info.altname); sprintf(path, "payloads/%s", info.altname);
payloadSize = fileRead(payloadAddress, path, maxPayloadSize); if(memcmp(mountPoint, "nand", 4))
} sprintf(absPath, "nand:/rw/luma/payloads/%s", info.altname);
else payloadSize = fileRead(payloadAddress, payloadPath, maxPayloadSize); 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); writeConfig(true);
char *argv[1] = {absPath};
memcpy(loaderAddress, loader_bin, loader_bin_size); memcpy(loaderAddress, loader_bin, loader_bin_size);
if(ISN3DS) kernel9Loader(NULL);
backupAndRestoreShaHash(true);
initScreens(); initScreens();
flushDCacheRange(loaderAddress, loader_bin_size); flushDCacheRange(loaderAddress, loader_bin_size);
flushICacheRange(loaderAddress, loader_bin_size); flushICacheRange(loaderAddress, loader_bin_size);
((void (*)(u32))loaderAddress)(payloadSize); ((void (*)(int, char **, u32))loaderAddress)(1, argv, 0x0000BEEF);
} }
void payloadMenu(void) void payloadMenu(void)
@ -190,11 +271,11 @@ void payloadMenu(void)
u32 nameLength = strlen(info.fname); 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); memcpy(payloadList[payloadNum], info.fname, nameLength);
payloadList[payloadNum][nameLength] = 0; payloadList[payloadNum][nameLength] = 0;
@ -258,7 +339,7 @@ void payloadMenu(void)
if(pressed != BUTTON_START) if(pressed != BUTTON_START)
{ {
sprintf(path, "payloads/%s.bin", payloadList[selectedPayload]); sprintf(path, "payloads/%s.firm", payloadList[selectedPayload]);
loadPayload(0, path); loadPayload(0, path);
error("The payload is too large or corrupted."); error("The payload is too large or corrupted.");
} }

View File

@ -32,12 +32,16 @@
#include "pin.h" #include "pin.h"
#include "crypto.h" #include "crypto.h"
#include "fmt.h" #include "fmt.h"
#include "memory.h"
extern CfgData configData; extern CfgData configData;
extern ConfigurationStatus needConfig; extern ConfigurationStatus needConfig;
extern FirmwareSource firmSource; extern FirmwareSource firmSource;
void main(void) u16 launchedFirmTidLow[8];
u16 launchedPath[42];
void main(int argc, char **argv)
{ {
bool isSafeMode = false, bool isSafeMode = false,
isNoForceFlagSet = false; isNoForceFlagSet = false;
@ -45,15 +49,59 @@ void main(void)
FirmwareType firmType; FirmwareType firmType;
FirmwareSource nandType; 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 //Mount SD or CTRNAND
bool isSdMode; 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; firmSource = FIRMWARE_SYSNAND;
if(!mountFs(false, true)) error("Failed to mount SD and CTRNAND."); if(!mountFs(false, true)) error("Failed to mount SD and CTRNAND.");
isSdMode = false; isSdMode = false;
} }
else
error("Launched from an unsupported location");
//Attempt to read the configuration file //Attempt to read the configuration file
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;

View File

@ -37,30 +37,6 @@
#include "utils.h" #include "utils.h"
#include "../build/bundled.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 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
{ {
u8 *temp = memsearch(pos, "NCCH", size, 4); 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); u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
*pos_fopen = fOpenOffset; *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; return 0;
} }

View File

@ -24,32 +24,31 @@
.align 4 .align 4
.global _start .global _start
_start: _start:
b start
.global launchedFirmTidLow
launchedFirmTidLow:
.hword 0, 0, 0, 0, 0, 0, 0, 0
start:
@ Disable interrupts @ Disable interrupts
mrs r0, cpsr mrs r4, cpsr
orr r0, #0x1C0 orr r4, #0x1C0
msr cpsr_cx, r0 msr cpsr_cx, r4
ldr r4, =0xBEEF
cmp r2, r4
movne r0, #0 @ check magic word
@ Change the stack pointer @ Change the stack pointer
mov sp, #0x27000000 mov sp, #0x27000000
@ Disable caches / MPU @ Disable caches / MPU
mrc p15, 0, r0, c1, c0, 0 @ read control register mrc p15, 0, r4, c1, c0, 0 @ read control register
bic r0, #(1<<12) @ - instruction cache disable bic r4, #(1<<12) @ - instruction cache disable
bic r0, #(1<<2) @ - data cache disable bic r4, #(1<<2) @ - data cache disable
bic r0, #(1<<0) @ - mpu disable bic r4, #(1<<0) @ - mpu disable
mcr p15, 0, r0, c1, c0, 0 @ write control register mcr p15, 0, r4, c1, c0, 0 @ write control register
@ Flush caches @ Flush caches
bl flushEntireDCache bl flushEntireDCache
bl flushEntireICache bl flushEntireICache
push {r0-r3}
@ Give read/write access to all the memory regions @ Give read/write access to all the memory regions
ldr r0, =0x3333333 ldr r0, =0x3333333
mcr p15, 0, r0, c5, c0, 2 @ write data access mcr p15, 0, r0, c5, c0, 2 @ write data access
@ -98,4 +97,5 @@ start:
sub r2, r0 sub r2, r0
bl memset32 bl memset32
pop {r0-r3}
b main b main

View File

@ -115,4 +115,5 @@ typedef enum FirmwareType
NATIVE_FIRM1X2X NATIVE_FIRM1X2X
} FirmwareType; } FirmwareType;
extern u16 launchedFirmTidLow[8]; //Defined in start.s extern u16 launchedFirmTidLow[8];
extern u16 launchedPath[42];