Skip to content

Commit

Permalink
Remove DLDI driver space from bootloader
Browse files Browse the repository at this point in the history
Fixes DSi data (such as CID) being overwritten in RAM
  • Loading branch information
RocketRobz committed Nov 2, 2024
1 parent 8a0ad45 commit 627a9c8
Show file tree
Hide file tree
Showing 32 changed files with 643 additions and 398 deletions.
37 changes: 1 addition & 36 deletions booter_fc/arm9/source/nds_loader_arm9.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,42 +390,7 @@ int runNdsFile (const char* filename, int argc, const char** argv) {
runNds9i(filename);
}

bool loadFromRam = (runNds9(filename) || (isDSiMode() && access("sd:/", F_OK) != 0));
const bool loadFromRam = (runNds9(filename) || (isDSiMode() && access("sd:/", F_OK) != 0));

bool havedsiSD = (argv[0][0]=='s' && argv[0][1]=='d');
installBootStub(havedsiSD);

return runNds (load_bin, load_bin_size, st.st_ino, true, (memcmp(io_dldi_data->friendlyName, "Default", 7) != 0), loadFromRam, argc, argv);
}


bool installBootStub(bool havedsiSD) {
#ifndef _NO_BOOTSTUB_
extern char *fake_heap_end;
struct __bootstub *bootstub = (struct __bootstub *)fake_heap_end;
u32 *bootloader = (u32*)(fake_heap_end+bootstub_bin_size);

memcpy(bootstub,bootstub_bin,bootstub_bin_size);
memcpy(bootloader,load_bin,load_bin_size);
bool ret = false;

bootloader[8] = isDSiMode();
if ( havedsiSD) {
ret = true;
bootloader[3] = 0; // don't dldi patch
bootloader[7] = 1; // use internal dsi SD code
} else {
ret = dldiPatchLoader((data_t*)bootloader, load_bin_size,false);
}
bootstub->arm9reboot = (VoidFn)(((u32)bootstub->arm9reboot)+fake_heap_end);
bootstub->arm7reboot = (VoidFn)(((u32)bootstub->arm7reboot)+fake_heap_end);
bootstub->bootsize = load_bin_size;

DC_FlushAll();

return ret;
#else
return true;
#endif

}
2 changes: 1 addition & 1 deletion settings/bootloader/load.ld
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENTRY(_start)

MEMORY {

vram : ORIGIN = 0x06000000, LENGTH = 128K
vram : ORIGIN = 0x06008000, LENGTH = 128K - 32K
}

__vram_start = ORIGIN(vram);
Expand Down
15 changes: 14 additions & 1 deletion settings/bootloader/source/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ void passArgs_ARM7 (void) {
argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned

if (ARM9_LEN > 0x380000) {
argDst = (u32*)0x02FFA000;
argDst = (u32*)(0x02FFC000 - ((argSize/4)*4));
} else
if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) {
u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8));
Expand Down Expand Up @@ -448,6 +448,19 @@ int main (void) {
#ifndef NO_SDMMC
sdRead = (dsiSD && dsiMode);
#endif
if (wantToPatchDLDI) {
toncset((u32*)0x06000000, 0, 0x8000);
if (*(u32*)0x02FF8004 == 0x69684320) { // DLDI ' Chi' string
const u16 dldiFileSize = 1 << *(u8*)0x02FF800D;
tonccpy((u32*)0x06000000, (u32*)0x02FF8000, (dldiFileSize > 0x4000) ? 0x4000 : dldiFileSize);
dldiClearBss();
} else if (*(u32*)0x02FF8000 == 0x53535A4C) { // LZ77 flag
dldiDecompressBinary();
} else {
return -1;
}
}

if (*(u32*)(0x2FFFD0C) == 0x4E44544C) {
limitedModeMemoryPit();
*(u32*)(0x2FFFD0C) = 0;
Expand Down
98 changes: 93 additions & 5 deletions settings/bootloader/source/dldi_patcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#ifndef NO_DLDI
#include <string.h>
#include <nds.h>
#include "common/tonccpy.h"
#include "dldi_patcher.h"

#define FIX_ALL 0x01
Expand Down Expand Up @@ -76,7 +77,7 @@ static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLe
addr_t i;
addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int));

for ( i = 0; i < dataChunkEnd; i++) {
for (i = 0; i < dataChunkEnd; i++) {
if (dataChunk[i] == searchChunk) {
if ((i*sizeof(int) + searchLen) > dataLen) {
return -1;
Expand Down Expand Up @@ -107,7 +108,7 @@ static void demangleMagicString(data_t *dest, const data_t *src) {

#define DEVICE_TYPE_DLDI 0x49444C44

extern data_t _dldi_start[];
static data_t* _dldi_start = (data_t*)0x06000000;

bool dldiPatchBinary (data_t *binData, u32 binSize) {

Expand Down Expand Up @@ -164,7 +165,7 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) {
// Remember how much space is actually reserved
pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace];
// Copy the DLDI patch into the application
memcpy (pAH, pDH, dldiFileSize);
tonccpy (pAH, pDH, dldiFileSize);

// Fix the section pointers in the header
writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset);
Expand All @@ -184,7 +185,7 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) {
writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset);

// Put the correct DLDI magic string back into the DLDI header
memcpy (pAH, dldiMagicString, sizeof (dldiMagicString));
tonccpy (pAH, dldiMagicString, sizeof (dldiMagicString));

if (pDH[DO_fixSections] & FIX_ALL) {
// Search through and fix pointers within the data section of the file
Expand Down Expand Up @@ -215,9 +216,96 @@ bool dldiPatchBinary (data_t *binData, u32 binSize) {

if (pDH[DO_fixSections] & FIX_BSS) {
// Initialise the BSS to 0
memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start));
toncset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start));
}

return true;
}

void dldiDecompressBinary (void) {
extern void LZ77_Decompress(u8* source, u8* destination);
LZ77_Decompress((u8*)0x02FF8004, (u8*)_dldi_start);

addr_t memOffset; // Offset of DLDI after the file is loaded into memory
addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly
addr_t ddmemOffset; // Original offset used in the DLDI file
addr_t ddmemStart; // Start of range that offsets can be in the DLDI file
addr_t ddmemEnd; // End of range that offsets can be in the DLDI file
addr_t ddmemSize; // Size of range that offsets can be in the DLDI file
addr_t addrIter;

data_t *pDH = _dldi_start;

memOffset = 0x06000000;
ddmemOffset = readAddr (pDH, DO_text_start);
relocationOffset = memOffset - ddmemOffset;

ddmemStart = readAddr (pDH, DO_text_start);
ddmemSize = (1 << pDH[DO_driverSize]);
ddmemEnd = ddmemStart + ddmemSize;

// Fix the section pointers in the header
writeAddr (pDH, DO_text_start, readAddr (pDH, DO_text_start) + relocationOffset);
writeAddr (pDH, DO_data_end, readAddr (pDH, DO_data_end) + relocationOffset);
writeAddr (pDH, DO_glue_start, readAddr (pDH, DO_glue_start) + relocationOffset);
writeAddr (pDH, DO_glue_end, readAddr (pDH, DO_glue_end) + relocationOffset);
writeAddr (pDH, DO_got_start, readAddr (pDH, DO_got_start) + relocationOffset);
writeAddr (pDH, DO_got_end, readAddr (pDH, DO_got_end) + relocationOffset);
writeAddr (pDH, DO_bss_start, readAddr (pDH, DO_bss_start) + relocationOffset);
writeAddr (pDH, DO_bss_end, readAddr (pDH, DO_bss_end) + relocationOffset);
// Fix the function pointers in the header
writeAddr (pDH, DO_startup, readAddr (pDH, DO_startup) + relocationOffset);
writeAddr (pDH, DO_isInserted, readAddr (pDH, DO_isInserted) + relocationOffset);
writeAddr (pDH, DO_readSectors, readAddr (pDH, DO_readSectors) + relocationOffset);
writeAddr (pDH, DO_writeSectors, readAddr (pDH, DO_writeSectors) + relocationOffset);
writeAddr (pDH, DO_clearStatus, readAddr (pDH, DO_clearStatus) + relocationOffset);
writeAddr (pDH, DO_shutdown, readAddr (pDH, DO_shutdown) + relocationOffset);

if (pDH[DO_fixSections] & FIX_ALL) {
// Search through and fix pointers within the data section of the file
for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) {
if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) {
writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset);
}
}
}

if (pDH[DO_fixSections] & FIX_GLUE) {
// Search through and fix pointers within the glue section of the file
for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) {
if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) {
writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset);
}
}
}

if (pDH[DO_fixSections] & FIX_GOT) {
// Search through and fix pointers within the Global Offset Table section of the file
for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) {
if ((ddmemStart <= readAddr(pDH, addrIter)) && (readAddr(pDH, addrIter) < ddmemEnd)) {
writeAddr (pDH, addrIter, readAddr(pDH, addrIter) + relocationOffset);
}
}
}

if (pDH[DO_fixSections] & FIX_BSS) {
// Initialise the BSS to 0
toncset (&pDH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start));
}
}

void dldiClearBss (void) {
data_t *pDH = _dldi_start;

addr_t ddmemSize = (1 << pDH[DO_driverSize]); // Size of range that offsets can be in the DLDI file

if (ddmemSize <= 0x4000) return; // For <= 16KB DLDI file, BSS has already been cleared

addr_t ddmemStart = readAddr (pDH, DO_text_start); // Start of range that offsets can be in the DLDI file

if (pDH[DO_fixSections] & FIX_BSS) {
// Initialise the BSS to 0
toncset (&pDH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start));
}
}
#endif
2 changes: 2 additions & 0 deletions settings/bootloader/source/dldi_patcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,7 @@
typedef signed int addr_t;
typedef unsigned char data_t;
bool dldiPatchBinary (data_t *binData, u32 binSize);
void dldiDecompressBinary (void);
void dldiClearBss (void);

#endif // DLDI_PATCHER_H
86 changes: 13 additions & 73 deletions settings/bootloader/source/io_dldi.s
Original file line number Diff line number Diff line change
Expand Up @@ -32,73 +32,6 @@


_dldi_start:
#ifndef NO_DLDI

@---------------------------------------------------------------------------------
@ Driver patch file standard header -- 16 bytes
#ifdef STANDARD_DLDI
.word 0xBF8DA5ED @ Magic number to identify this region
#else
.word 0xBF8DA5EE @ Magic number to identify this region
#endif
.asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator)
.byte 0x01 @ Version number
.byte 0x0f @ 32KiB @ Log [base-2] of the size of this driver in bytes.
.byte 0x00 @ Sections to fix
.byte 0x0f @ 32KiB @ Log [base-2] of the allocated space in bytes.

@---------------------------------------------------------------------------------
@ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes
.align 4
.asciz "Loader (No interface)"

@---------------------------------------------------------------------------------
@ Offsets to important sections within the data -- 32 bytes
.align 6
.word _dldi_start @ data start
.word _dldi_end @ data end
.word 0x00000000 @ Interworking glue start -- Needs address fixing
.word 0x00000000 @ Interworking glue end
.word 0x00000000 @ GOT start -- Needs address fixing
.word 0x00000000 @ GOT end
.word 0x00000000 @ bss start -- Needs setting to zero
.word 0x00000000 @ bss end
@---------------------------------------------------------------------------------
@ IO_INTERFACE data -- 32 bytes
_io_dldi:
.ascii "DLDI" @ ioType
.word 0x00000000 @ Features
.word _DLDI_startup @
.word _DLDI_isInserted @
.word _DLDI_readSectors @ Function pointers to standard device driver functions
.word _DLDI_writeSectors @
.word _DLDI_clearStatus @
.word _DLDI_shutdown @


@---------------------------------------------------------------------------------

_DLDI_startup:
_DLDI_isInserted:
_DLDI_readSectors:
_DLDI_writeSectors:
_DLDI_clearStatus:
_DLDI_shutdown:
mov r0, #0x00 @ Return false for every function
bx lr



@---------------------------------------------------------------------------------
.align
.pool

.space (_dldi_start + 32768) - . @ Fill to 32KiB

_dldi_end:
.end
@---------------------------------------------------------------------------------
#else
@---------------------------------------------------------------------------------
@ IO_INTERFACE data -- 32 bytes
_io_dldi:
Expand All @@ -111,14 +44,21 @@ _io_dldi:
.word _DLDI_clearStatus @
.word _DLDI_shutdown @

_DLDI_startup:
_DLDI_startup:
mov r12, #0x06000000
ldr pc, [r12, #0x68]
_DLDI_isInserted:
mov r12, #0x06000000
ldr pc, [r12, #0x6C]
_DLDI_readSectors:
mov r12, #0x06000000
ldr pc, [r12, #0x70]
_DLDI_writeSectors:
mov r12, #0x06000000
ldr pc, [r12, #0x74]
_DLDI_clearStatus:
mov r12, #0x06000000
ldr pc, [r12, #0x78]
_DLDI_shutdown:
mov r0, #0x00 @ Return false for every function
bx lr


#endif
mov r12, #0x06000000
ldr pc, [r12, #0x7C]
27 changes: 27 additions & 0 deletions settings/bootloader/source/lzss.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include <nds/ndstypes.h>
#include <string.h>

void LZ77_Decompress(u8* source, u8* destination) {
u32 leng = (source[1] | (source[2] << 8) | (source[3] << 16));
int Offs = 4;
int dstoffs = 0;
while (true) {
u8 header = source[Offs++];
for (int i = 0; i < 8; i++) {
if ((header & 0x80) == 0) destination[dstoffs++] = source[Offs++];
else
{
u8 a = source[Offs++];
u8 b = source[Offs++];
int offs = (((a & 0xF) << 8) | b) + 1;
int length = (a >> 4) + 3;
for (int j = 0; j < length; j++) {
destination[dstoffs] = destination[dstoffs - offs];
dstoffs++;
}
}
if (dstoffs >= (int)leng) return;
header <<= 1;
}
}
}
14 changes: 13 additions & 1 deletion title/arm9/source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1820,6 +1820,18 @@ int titleMode(void)
4: Run temporary DSiWare
*/

if ((strcmp(io_dldi_data->friendlyName, "NAND FLASH CARD LIBFATNRIO") == 0) && (*(u32*)0x02FF8000 != 0x53535A4C)) {
FILE* file = fopen("nitro:/dldi/nrio.lz77", "rb");
fread((void*)0x02FF8004, 1, 0x3FFC, file);
fclose(file);

*(u32*)0x02FF8000 = 0x53535A4C;
}

#ifndef _NO_BOOTSTUB_
installBootStub(sdFound());
#endif

if (isDSiMode() && sdFound()) {
if ((access("sd:/_nds/bios9i.bin", F_OK) != 0) && (access("sd:/_nds/bios9i_part1.bin", F_OK) != 0)) {
extern char copyBuf[0x8000];
Expand Down Expand Up @@ -1884,7 +1896,7 @@ int titleMode(void)
}
}

bool is3DS = fifoGetValue32(FIFO_USER_05) != 0xD2;
const bool is3DS = fifoGetValue32(FIFO_USER_05) != 0xD2;

useTwlCfg = (REG_SCFG_EXT!=0 && (*(u8*)0x02000400 != 0) && (*(u8*)0x02000401 == 0) && (*(u8*)0x02000402 == 0) && (*(u8*)0x02000404 == 0) && (*(u8*)0x02000448 != 0));
bool nandMounted = false;
Expand Down
2 changes: 1 addition & 1 deletion title/bootloader/load.ld
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ ENTRY(_start)

MEMORY {

vram : ORIGIN = 0x06000000, LENGTH = 128K
vram : ORIGIN = 0x06008000, LENGTH = 128K - 32K
}

__vram_start = ORIGIN(vram);
Expand Down
Loading

0 comments on commit 627a9c8

Please sign in to comment.