Rewrite the LayeredFS code to check the mount name properly and use ro/data padding for the custom path
This commit is contained in:
parent
b1c07c6204
commit
e231275cbe
@ -52,16 +52,16 @@ _start:
|
|||||||
; it from its original archive like nothing happened
|
; it from its original archive like nothing happened
|
||||||
fsRedir:
|
fsRedir:
|
||||||
stmfd sp!, {r0-r12, lr}
|
stmfd sp!, {r0-r12, lr}
|
||||||
ldrb r12, [r1]
|
addr r3, romFsMount
|
||||||
cmp r12, #0x72 ; 'r', should include "rom:", "rom2:" and "rex:"
|
bl compare
|
||||||
ldrne r11, [pc, #updateRomFsStart-.-8]
|
addne r3, pc, #updateRomFsMount-.-8
|
||||||
cmpne r12, r11
|
blne compare
|
||||||
bne endRedir
|
bne endRedir
|
||||||
sub sp, sp, #0x400
|
sub sp, sp, #0x400
|
||||||
pathRedir:
|
pathRedir:
|
||||||
stmfd sp!, {r0-r3}
|
stmfd sp!, {r0-r3}
|
||||||
add r0, sp, #0x10
|
add r0, sp, #0x10
|
||||||
addr r3, customPath
|
load r3, customPath
|
||||||
pathRedir_1:
|
pathRedir_1:
|
||||||
ldrb r2, [r3], #1
|
ldrb r2, [r3], #1
|
||||||
strh r2, [r0], #2
|
strh r2, [r0], #2
|
||||||
@ -89,13 +89,26 @@ _start:
|
|||||||
bxeq lr
|
bxeq lr
|
||||||
b _fsRedir + 4
|
b _fsRedir + 4
|
||||||
|
|
||||||
|
compare:
|
||||||
|
mov r9, r1
|
||||||
|
add r10, r3, #4
|
||||||
|
loop:
|
||||||
|
ldrb r12, [r3], #1
|
||||||
|
ldrb r11, [r9], #2
|
||||||
|
cmp r11, r12
|
||||||
|
bxne lr
|
||||||
|
cmp r10, r3
|
||||||
|
bne loop
|
||||||
|
bx lr
|
||||||
|
|
||||||
.pool
|
.pool
|
||||||
.align 4
|
.align 4
|
||||||
archiveName : .dcb "lf:", 0
|
archiveName : .dcb "lf:", 0
|
||||||
fsMountArchive : .word 0xdead0005
|
fsMountArchive : .word 0xdead0005
|
||||||
fsRegisterArchive : .word 0xdead0006
|
fsRegisterArchive : .word 0xdead0006
|
||||||
archiveId : .word 0xdead0007
|
archiveId : .word 0xdead0007
|
||||||
updateRomFsStart : .word 0xdead0008
|
romFsMount : .dcb "rom:"
|
||||||
|
updateRomFsMount : .word 0xdead0008
|
||||||
customPath : .word 0xdead0004
|
customPath : .word 0xdead0004
|
||||||
|
|
||||||
.close
|
.close
|
||||||
|
@ -158,7 +158,7 @@ static Result load_code(u64 progid, prog_addrs_t *shared, u64 prog_handle, int i
|
|||||||
u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8);
|
u16 progver = g_exheader.codesetinfo.flags.remasterversion[0] | (g_exheader.codesetinfo.flags.remasterversion[1] << 8);
|
||||||
|
|
||||||
// patch
|
// patch
|
||||||
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12, g_exheader.codesetinfo.text.codesize, g_exheader.codesetinfo.ro.codesize);
|
patchCode(progid, progver, (u8 *)shared->text_addr, shared->total_size << 12, g_exheader.codesetinfo.text.codesize, g_exheader.codesetinfo.ro.codesize, g_exheader.codesetinfo.data.codesize, g_exheader.codesetinfo.ro.address, g_exheader.codesetinfo.data.address);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -328,48 +328,72 @@ static inline bool findLayeredFsSymbols(u8 *code, u32 size, u32 *fsMountArchive,
|
|||||||
return found == 4;
|
return found == 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool findLayeredFsPayloadOffset(u8 *code, u32 size, u32 *payloadOffset)
|
static inline bool findLayeredFsPayloadOffset(u8 *code, u32 size, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress, u32 *payloadOffset, u32 *pathOffset, u32 *pathAddress)
|
||||||
{
|
{
|
||||||
|
u32 roundedTextSize = ((size + 4095) & 0xFFFFF000),
|
||||||
|
roundedRoSize = ((roSize + 4095) & 0xFFFFF000),
|
||||||
|
roundedDataSize = ((dataSize + 4095) & 0xFFFFF000);
|
||||||
|
|
||||||
//First check for sufficient padding at the end of the .text segment
|
//First check for sufficient padding at the end of the .text segment
|
||||||
if(((size + 4095) & 0xFFFFF000) - size >= romfsredir_bin_size)
|
if(roundedTextSize - size >= romfsredir_bin_size) *payloadOffset = size;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
*payloadOffset = size;
|
//If there isn't enough padding look for the "throwFatalError" function to replace
|
||||||
|
u32 svcConnectToPort = 0xFFFFFFFF;
|
||||||
|
|
||||||
return true;
|
for(u32 addr = 4; svcConnectToPort == 0xFFFFFFFF && addr <= size - 4; addr += 4)
|
||||||
}
|
|
||||||
|
|
||||||
//If there isn't enough padding look for the "throwFatalError" function to replace
|
|
||||||
u32 svcConnectToPort = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
for(u32 addr = 4; svcConnectToPort == 0xFFFFFFFF && addr <= size - 4; addr += 4)
|
|
||||||
{
|
|
||||||
if(*(u32 *)(code + addr) == 0xEF00002D)
|
|
||||||
svcConnectToPort = addr - 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(svcConnectToPort != 0xFFFFFFFF)
|
|
||||||
{
|
|
||||||
u32 func = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
for(u32 i = 4; func == 0xFFFFFFFF && i <= size - 4; i += 4)
|
|
||||||
{
|
{
|
||||||
if(*(u32 *)(code + i) != MAKE_BRANCH_LINK(i, svcConnectToPort)) continue;
|
if(*(u32 *)(code + addr) == 0xEF00002D)
|
||||||
|
svcConnectToPort = addr - 4;
|
||||||
func = findFunctionStart(code, i);
|
|
||||||
|
|
||||||
for(u32 pos = func + 4; func != 0xFFFFFFFF && pos <= size - 4 && *(u16 *)(code + pos + 2) != 0xE92D; pos += 4)
|
|
||||||
if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(func != 0xFFFFFFFF)
|
if(svcConnectToPort != 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
*payloadOffset = func;
|
u32 func = 0xFFFFFFFF;
|
||||||
|
|
||||||
return true;
|
for(u32 i = 4; func == 0xFFFFFFFF && i <= size - 4; i += 4)
|
||||||
|
{
|
||||||
|
if(*(u32 *)(code + i) != MAKE_BRANCH_LINK(i, svcConnectToPort)) continue;
|
||||||
|
|
||||||
|
func = findFunctionStart(code, i);
|
||||||
|
|
||||||
|
for(u32 pos = func + 4; func != 0xFFFFFFFF && pos <= size - 4 && *(u16 *)(code + pos + 2) != 0xE92D; pos += 4)
|
||||||
|
if(*(u32 *)(code + pos) == 0xE200167E) func = 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(func != 0xFFFFFFFF)
|
||||||
|
*payloadOffset = func;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
if(roundedRoSize - roSize >= 39)
|
||||||
|
{
|
||||||
|
*pathOffset = roundedTextSize + roSize;
|
||||||
|
*pathAddress = roAddress + roSize;
|
||||||
|
}
|
||||||
|
else if(roundedDataSize - dataSize >= 39)
|
||||||
|
{
|
||||||
|
*pathOffset = roundedTextSize + roundedRoSize + dataSize;
|
||||||
|
*pathAddress = dataAddress + dataSize;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u32 strSpace = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
for(u32 addr = 0; strSpace == 0xFFFFFFFF && addr <= size - 4; addr += 4)
|
||||||
|
{
|
||||||
|
if(*(u32 *)(code + addr) == 0xE3A00B42)
|
||||||
|
strSpace = findFunctionStart(code, addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strSpace != 0xFFFFFFFF)
|
||||||
|
{
|
||||||
|
*pathOffset = strSpace;
|
||||||
|
*pathAddress = 0x100000 + strSpace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *payloadOffset != 0 && *pathOffset != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool applyCodeIpsPatch(u64 progId, u8 *code, u32 size)
|
static inline bool applyCodeIpsPatch(u64 progId, u8 *code, u32 size)
|
||||||
@ -514,7 +538,7 @@ exit:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress)
|
||||||
{
|
{
|
||||||
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/romfs"
|
/* Here we look for "/luma/titles/[u64 titleID in hex, uppercase]/romfs"
|
||||||
If it exists it should be a folder containing ROMFS files */
|
If it exists it should be a folder containing ROMFS files */
|
||||||
@ -530,23 +554,23 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
|||||||
fsRegisterArchive = 0xFFFFFFFF,
|
fsRegisterArchive = 0xFFFFFFFF,
|
||||||
fsTryOpenFile = 0xFFFFFFFF,
|
fsTryOpenFile = 0xFFFFFFFF,
|
||||||
fsOpenFileDirectly = 0xFFFFFFFF,
|
fsOpenFileDirectly = 0xFFFFFFFF,
|
||||||
payloadOffset;
|
payloadOffset = 0,
|
||||||
|
pathOffset = 0,
|
||||||
|
pathAddress;
|
||||||
|
|
||||||
if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) ||
|
if(!findLayeredFsSymbols(code, textSize, &fsMountArchive, &fsRegisterArchive, &fsTryOpenFile, &fsOpenFileDirectly) ||
|
||||||
!findLayeredFsPayloadOffset(code, textSize, &payloadOffset)) return false;
|
!findLayeredFsPayloadOffset(code, textSize, roSize, dataSize, roAddress, dataAddress, &payloadOffset, &pathOffset, &pathAddress)) return false;
|
||||||
|
|
||||||
static const char *updateRomFsMounts[] = { "patch:",
|
static const char *updateRomFsMounts[] = { "rom2:",
|
||||||
"ext:" };
|
"rex:"
|
||||||
char updateRomFsStart = 'r';
|
"patch:",
|
||||||
u32 i;
|
"ext:",
|
||||||
|
"rom:" };
|
||||||
|
u32 updateRomFsIndex;
|
||||||
|
|
||||||
//Locate update RomFSes
|
//Locate update RomFSes
|
||||||
for(i = 0; i < sizeof(updateRomFsMounts) / sizeof(char *); i++)
|
for(updateRomFsIndex = 0; updateRomFsIndex < sizeof(updateRomFsMounts) / sizeof(char *) - 1; updateRomFsIndex++)
|
||||||
{
|
if(memsearch(code, updateRomFsMounts[updateRomFsIndex], size, strnlen(updateRomFsMounts[updateRomFsIndex], 255)) != NULL) break;
|
||||||
if(memsearch(code, updateRomFsMounts[i], size, strnlen(updateRomFsMounts[i], 255)) != NULL) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i != sizeof(updateRomFsMounts) / sizeof(char *)) updateRomFsStart = updateRomFsMounts[i][0];
|
|
||||||
|
|
||||||
//Setup the payload
|
//Setup the payload
|
||||||
u8 *payload = code + payloadOffset;
|
u8 *payload = code + payloadOffset;
|
||||||
@ -554,7 +578,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
|||||||
|
|
||||||
//Insert symbols in the payload
|
//Insert symbols in the payload
|
||||||
u32 *payload32 = (u32 *)payload;
|
u32 *payload32 = (u32 *)payload;
|
||||||
for(i = 0; i < romfsredir_bin_size / 4; i++)
|
for(u32 i = 0; i < romfsredir_bin_size / 4; i++)
|
||||||
{
|
{
|
||||||
switch(payload32[i])
|
switch(payload32[i])
|
||||||
{
|
{
|
||||||
@ -571,8 +595,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
|||||||
payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsTryOpenFile + 4);
|
payload32[i] = MAKE_BRANCH(payloadOffset + i * 4, fsTryOpenFile + 4);
|
||||||
break;
|
break;
|
||||||
case 0xdead0004:
|
case 0xdead0004:
|
||||||
memcpy(payload32 + i, "lf:", 3);
|
payload32[i] = pathAddress;
|
||||||
memcpy((u8 *)(payload32 + i) + 3, path, sizeof(path));
|
|
||||||
break;
|
break;
|
||||||
case 0xdead0005:
|
case 0xdead0005:
|
||||||
payload32[i] = 0x100000 + fsMountArchive;
|
payload32[i] = 0x100000 + fsMountArchive;
|
||||||
@ -584,11 +607,14 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
|||||||
payload32[i] = archiveId;
|
payload32[i] = archiveId;
|
||||||
break;
|
break;
|
||||||
case 0xdead0008:
|
case 0xdead0008:
|
||||||
payload32[i] = (u32)updateRomFsStart;
|
memcpy(payload32 + i, updateRomFsMounts[updateRomFsIndex], 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(code + pathOffset, "lf:", 3);
|
||||||
|
memcpy(code + pathOffset + 3, path, sizeof(path));
|
||||||
|
|
||||||
//Place the hooks
|
//Place the hooks
|
||||||
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, payloadOffset);
|
*(u32 *)(code + fsOpenFileDirectly) = MAKE_BRANCH(fsOpenFileDirectly, payloadOffset);
|
||||||
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, payloadOffset + 12);
|
*(u32 *)(code + fsTryOpenFile) = MAKE_BRANCH(fsTryOpenFile, payloadOffset + 12);
|
||||||
@ -596,7 +622,7 @@ static inline bool patchLayeredFs(u64 progId, u8 *code, u32 size, u32 textSize)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize)
|
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress)
|
||||||
{
|
{
|
||||||
loadCFWInfo();
|
loadCFWInfo();
|
||||||
|
|
||||||
@ -760,7 +786,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
|
|||||||
patch[] = u"C";
|
patch[] = u"C";
|
||||||
|
|
||||||
//Use SecureInfo_C
|
//Use SecureInfo_C
|
||||||
if(patchMemory(code + textSize, roSize,
|
if(patchMemory(code + ((textSize + 4095) & 0xFFFFF000), roSize,
|
||||||
pattern,
|
pattern,
|
||||||
sizeof(pattern) - 2, 22,
|
sizeof(pattern) - 2, 22,
|
||||||
patch,
|
patch,
|
||||||
@ -858,7 +884,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 ro
|
|||||||
if(!loadTitleCodeSection(progId, code, size) ||
|
if(!loadTitleCodeSection(progId, code, size) ||
|
||||||
!applyCodeIpsPatch(progId, code, size) ||
|
!applyCodeIpsPatch(progId, code, size) ||
|
||||||
!loadTitleLocaleConfig(progId, ®ionId, &languageId) ||
|
!loadTitleLocaleConfig(progId, ®ionId, &languageId) ||
|
||||||
!patchLayeredFs(progId, code, size, textSize)) goto error;
|
!patchLayeredFs(progId, code, size, textSize, roSize, dataSize, roAddress, dataAddress)) goto error;
|
||||||
|
|
||||||
if(regionId != 0xFF)
|
if(regionId != 0xFF)
|
||||||
{
|
{
|
||||||
|
@ -44,4 +44,4 @@ enum flags
|
|||||||
ISSAFEMODE
|
ISSAFEMODE
|
||||||
};
|
};
|
||||||
|
|
||||||
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize);
|
void patchCode(u64 progId, u16 progVer, u8 *code, u32 size, u32 textSize, u32 roSize, u32 dataSize, u32 roAddress, u32 dataAddress);
|
||||||
|
Reference in New Issue
Block a user