Add stage2 loader

* Can now boot stage2 (in safe block mode) if holding L-Shoulder +
R-Shoulder + A + B + DPAD Up on boot. This allows using built in stage2
usb update mode for "bootleg" style N-Cards that have Xulumenu
installed.

* This button combo will not do anything for regular N-Card users as
they already have a proper stage2 section on nand and it will always end
up booting to USB update mode with this button combo before xulumenu can
boot.
This commit is contained in:
ApacheThunder 2024-10-26 00:18:57 -05:00
parent b621b163c8
commit 2550af0c99
26 changed files with 66 additions and 48 deletions

View File

@ -10,7 +10,7 @@ export TOPDIR := $(CURDIR)
include $(DEVKITARM)/ds_rules
.PHONY: data bootloader bootloaderalt clean
.PHONY: data bootloader udiskloader clean
#---------------------------------------------------------------------------------
# main targets
@ -37,15 +37,15 @@ data:
bootloader: data
$(MAKE) -C bootloader LOADBIN=$(TOPDIR)/data/load.bin
bootloaderalt: data
$(MAKE) -C bootloaderalt LOADBIN=$(TOPDIR)/data/loadAlt.bin
udiskloader: data
$(MAKE) -C udiskloader LOADBIN=$(TOPDIR)/data/udiskloader.bin
#---------------------------------------------------------------------------------
arm7/$(TARGET).elf:
$(MAKE) -C arm7
#---------------------------------------------------------------------------------
arm9/$(TARGET).elf: bootloader bootloaderalt
arm9/$(TARGET).elf: bootloader udiskloader
$(MAKE) -C arm9
#---------------------------------------------------------------------------------
@ -53,6 +53,6 @@ clean:
$(MAKE) -C arm9 clean
$(MAKE) -C arm7 clean
$(MAKE) -C bootloader clean
$(MAKE) -C bootloaderalt clean
$(MAKE) -C udiskloader clean
rm -rf data
rm -f $(TARGET).nds

View File

@ -30,3 +30,4 @@ int main(void) {
}
return 0;
}

BIN
arm9/binaries/stage2.srl Normal file

Binary file not shown.

Binary file not shown.

View File

@ -8,6 +8,8 @@ extern "C" {
extern void udiskData();
extern void udiskData_end();
extern void stage2Data();
extern void stage2_end();
#ifdef __cplusplus
}

View File

@ -1,8 +1,12 @@
.arm
.global udiskData, udiskData_end
.global udiskData, udiskData_end, stage2Data, stage2_end
udiskData:
.incbin "../binaries/udisk.srl"
udiskData_end:
stage2Data:
.incbin "../binaries/stage2.srl"
stage2_end:

View File

@ -67,15 +67,15 @@ int FileBrowser() {
// Construct a command line
vector<string> argarray;
if (!argsFillArray(filename, argarray)) {
iprintf("Invalid NDS or arg file selected\n");
iprintf("\n\nInvalid NDS or arg file selected\n");
} else {
iprintf("Running %s with %d parameters\n", argarray[0].c_str(), argarray.size());
iprintf("\n\nRunning %s with %d\nparameters\n", argarray[0].c_str(), argarray.size());
// Make a copy of argarray using C strings, for the sake of runNdsFile
vector<const char*> c_args;
for (const auto& arg: argarray) { c_args.push_back(arg.c_str()); }
// Try to run the NDS file with the given arguments
int err = runNdsFile(c_args[0], c_args.size(), &c_args[0]);
iprintf("Start failed. Error %i\n", err);
iprintf("\n\nStart failed. Error %i\n", err);
}
argarray.clear();
while (1) {
@ -97,17 +97,23 @@ int RecoveryPrompt(void) {
scanKeys();
if(keysDown() & KEY_A)break;
}
return runUdisk();
return runSRLbinary(false);
}
int main(void) {
// Any error results in starting integrated uDisk 1.45 SRL as fall back
scanKeys();
if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R))return RecoveryPrompt(); // Recovery option if FAT init hangs
u32 KeysHeld = keysHeld();
if ((KeysHeld & KEY_L) && (KeysHeld & KEY_R) && (KeysHeld & KEY_A) && (KeysHeld & KEY_B) && (KeysHeld & KEY_UP)) {
return runSRLbinary(true); // Recovery option if need to boot stage2
} else if ((KeysHeld & KEY_L) && (KeysHeld & KEY_R)) {
return RecoveryPrompt(); // Recovery option if FAT init hangs
}
if (!fatInitDefault())return RecoveryPrompt();
if((access("/boot.nds", F_OK) == 0) && !(keysHeld() & KEY_B))runNdsFile("/boot.nds", 0, NULL);
if((access("/udisk.nds", F_OK) == 0) && !(keysHeld() & KEY_B))runNdsFile("/udisk.nds", 0, NULL);
if (!(KeysHeld & KEY_B)) {
if((access("/boot.nds", F_OK) == 0))return runNdsFile("/boot.nds", 0, NULL);
if((access("/udisk.nds", F_OK) == 0))return runNdsFile("/udisk.nds", 0, NULL);
}
FileBrowser();
return RecoveryPrompt();
}

View File

@ -28,7 +28,7 @@
#include <fat.h>
#include "load_bin.h"
#include "loadAlt_bin.h"
#include "udiskloader_bin.h"
#include "binaries.h"
#include "tonccpy.h"
@ -229,8 +229,12 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) {
return true;
}
int runUdisk() {
tonccpy((void*)TMP_DATA, (void*)udiskData, (udiskData_end - udiskData));
int runSRLbinary(bool isStage2) {
if (isStage2) {
tonccpy((void*)TMP_DATA, (void*)stage2Data, (stage2_end - stage2Data));
} else {
tonccpy((void*)TMP_DATA, (void*)udiskData, (udiskData_end - udiskData));
}
// Start Bootloader
irqDisable(IRQ_ALL);
// Direct CPU access to VRAM bank D
@ -238,14 +242,14 @@ int runUdisk() {
// Clear VRAM
vramset (LCDC_BANK_D, 0x0000, 128 * 1024);
// Load the loader/patcher into the correct address
vramcpy (LCDC_BANK_D, loadAlt_bin, loadAlt_bin_size);
vramcpy (LCDC_BANK_D, udiskloader_bin, udiskloader_bin_size);
// Give the VRAM to the ARM7
VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000;
// Reset into a passme loop
REG_EXMEMCNT = 0xFFFF;
*((vu32*)0x027FFFFC) = 0;
*((vu32*)0x027FFE04) = (u32)0xE59FF018;
*((vu32*)0x027FFE24) = (u32)0x027FFE04;
*((vu32*)0x02FFFFFC) = 0;
*((vu32*)0x02FFFE04) = (u32)0xE59FF018;
*((vu32*)0x02FFFE24) = (u32)0x02FFFE04;
resetARM7(0x06020000);
swiSoftReset();
return 0;

View File

@ -36,7 +36,7 @@ typedef enum {
#define LOAD_DEFAULT_NDS 0
int runUdisk();
int runSRLbinary(bool isStage2);
eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv);

View File

@ -285,6 +285,17 @@ void startBinary_ARM7 (void) {
while(REG_VCOUNT==191);
// copy NDS ARM9 start address into the header, starting ARM9
*((vu32*)0x02FFFE24) = TEMP_ARM9_START_ADDRESS;
bool isXmenu = false;
switch (*((vu16*)0x02FFFF5E)) {
case 0xF63D: { isXmenu = true; }break;
case 0x0695: { isXmenu = true; }break;
case 0xE4C4: { isXmenu = true; }break;
case 0x918C: { isXmenu = true; }break;
}
ARM9_START_FLAG = 1;
// Start ARM7
VoidFn arm7code = *(VoidFn*)(0x2FFFE34);
@ -294,9 +305,7 @@ void startBinary_ARM7 (void) {
int sdmmc_sd_readsectors(u32 sector_no, u32 numsectors, void *out);
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Main function
bool sdmmc_inserted() {
return true;
}
bool sdmmc_inserted() { return true; }
bool sdmmc_startup() {
sdmmc_controller_init(true);
@ -324,18 +333,9 @@ int main (void) {
#endif
u32 fileCluster = storedFileCluster;
// Init card
if(!FAT_InitFiles(initDisc))
{
return -1;
}
if ((fileCluster < CLUSTER_FIRST) || (fileCluster >= CLUSTER_EOF)) /* Invalid file cluster specified */
{
fileCluster = getBootFileCluster(bootName);
}
if (fileCluster == CLUSTER_FREE)
{
return -1;
}
if(!FAT_InitFiles(initDisc))return -1;
if ((fileCluster < CLUSTER_FIRST) || (fileCluster >= CLUSTER_EOF))fileCluster = getBootFileCluster(bootName); /* Invalid file cluster specified */
if (fileCluster == CLUSTER_FREE)return -1;
// ARM9 clears its memory part 2
// copy ARM9 function to RAM, and make the ARM9 jump to it
@ -379,7 +379,8 @@ int main (void) {
#endif
// Pass command line arguments to loaded program
passArgs_ARM7();
startBinary_ARM7();
return 0;

View File

@ -12,7 +12,7 @@ endif
# SOURCES is a list of directories containing source code
# INCLUDES is a list of directories containing extra header files
#---------------------------------------------------------------------------------
TARGET := loadAlt
TARGET := udiskloader
BUILD := build
SOURCES := source source/patches
INCLUDES := build ../include
@ -24,9 +24,9 @@ SPECS := specs
#---------------------------------------------------------------------------------
ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi
CFLAGS := -g -Wall -O2\
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
-fomit-frame-pointer\
CFLAGS := -g -Wall -O2 \
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer \
-fomit-frame-pointer \
-ffast-math \
$(ARCH)

View File

@ -5,7 +5,7 @@ ENTRY(_start)
MEMORY {
vram : ORIGIN = 0x06020000, LENGTH = 64K
arm9ram : ORIGIN = 0x027FD800, LENGTH = 4K
arm9ram : ORIGIN = 0x02FFD800, LENGTH = 4K
}
__vram_start = ORIGIN(vram);

View File

@ -36,7 +36,7 @@ _start:
bl CopyMem
@ Start ARM9 binary
ldr r0, =0x027FFE24
ldr r0, =0x02FFFE24
ldr r1, =_arm9_start
str r1, [r0]

View File

@ -49,7 +49,7 @@
extern void arm7_clearmem (void* loc, size_t len);
extern void arm7_reset (void);
#define NDS_HEADER 0x027FFE00
#define NDS_HEADER 0x02FFFE00
#define TMP_DATA 0x02100000

View File

@ -64,7 +64,7 @@ arm7_reset:
@ ipcSendState(ARM7_BOOT)
strh r0, [r12]
ldr r0,=0x27FFE34
ldr r0,=0x2FFFE34
ldr r0,[r0]
bx r0

View File

@ -100,7 +100,7 @@ arm9_reset:
@ while (ipcRecvState() != ARM7_BOOT);
bl waitsync
ldr r10, =0x27FFE24
ldr r10, =0x2FFFE24
ldr r2, [r10]
@ Switch MPU to startup default
@ -130,6 +130,6 @@ mpu_initial_data:
.word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3
.word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4
.word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6
.word 0x027ff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB
.word 0x02fff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB
.word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size
itcm_reset_code_end: