From 2e5c142f3b66e5bca3646fa9635ed06ec6d59a30 Mon Sep 17 00:00:00 2001 From: EllipticEllipsis <73679967+EllipticEllipsis@users.noreply.github.com> Date: Thu, 11 Nov 2021 15:29:22 +0000 Subject: [PATCH] pfschecker OK (#429) * pfschecker OK * Clean up contpfs a bit * Add prototype to pfs.h * Format * Update src/libultra/io/pfschecker.c Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> Co-authored-by: Tharo <17233964+Thar0@users.noreply.github.com> --- include/PR/pfs.h | 3 + include/functions.h | 3 - src/libultra/io/contpfs.c | 117 ++++++++++++------- src/libultra/io/pfschecker.c | 212 ++++++++++++++++++++++++++++++++++- 4 files changed, 289 insertions(+), 46 deletions(-) diff --git a/include/PR/pfs.h b/include/PR/pfs.h index ff7f72bc58..135a6b56c7 100644 --- a/include/PR/pfs.h +++ b/include/PR/pfs.h @@ -134,4 +134,7 @@ typedef struct { /* 0x101 */ u8 map[PFS_INODE_DIST_MAP]; } __OSInodeCache; // size = 0x202 +s32 __osGetId(OSPfs* pfs); +s32 osPfsChecker(OSPfs* pfs); + #endif diff --git a/include/functions.h b/include/functions.h index 310ca6a14d..f189f0f136 100644 --- a/include/functions.h +++ b/include/functions.h @@ -332,7 +332,6 @@ u16 __osSumcalc(u8* ptr, s32 length); s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum); s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid); // void __osCheckPackId(void); -// void __osGetId(void); s32 __osCheckId(OSPfs* pfs); s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank); u32 osGetCount(void); @@ -427,8 +426,6 @@ u32 __osGetFpcCsr(void); // void osPfsInitPak(void); // void __osPfsCheckRamArea(void); // void osPfsChecker(void); -// void corrupted_init(void); -// void corrupted(void); u32 osAiGetLength(void); s32 osEPiWriteIo(OSPiHandle* pihandle, u32 devAddr, u32 data); void osMapTLBRdb(void); diff --git a/src/libultra/io/contpfs.c b/src/libultra/io/contpfs.c index 42009674f0..3dd0c96ca8 100644 --- a/src/libultra/io/contpfs.c +++ b/src/libultra/io/contpfs.c @@ -27,7 +27,7 @@ s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum) { s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) { s32 ret = 0; - u8 temp[BLOCKSIZE]; + u8 buf[BLOCKSIZE]; u8 comp[BLOCKSIZE]; u8 mask = 0; s32 i, j = 0; @@ -38,46 +38,60 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) { newid->serialMid = badid->serialMid; newid->serialLow = badid->serialLow; - if ((pfs->activebank != 0) && ((ret = __osPfsSelectBank(pfs, 0)) != 0)) { - return ret; + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { + return ret; + } } do { - if ((ret = __osPfsSelectBank(pfs, j)) != 0) { + ret = __osPfsSelectBank(pfs, j); + if (ret != 0) { return ret; } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, temp)) != 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, 0, buf); + if (ret != 0) { return ret; } - temp[0] = j | 0x80; + buf[0] = j | 0x80; for (i = 1; i < BLOCKSIZE; i++) { - temp[i] = ~temp[i]; + buf[i] = ~buf[i]; } - if ((ret = __osContRamWrite(pfs->queue, pfs->channel, 0, temp, 0)) != 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, 0, buf, 0); + if (ret != 0) { return ret; } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, comp)) != 0) { + + ret = __osContRamRead(pfs->queue, pfs->channel, 0, comp); + if (ret != 0) { return (ret); } + for (i = 0; i < BLOCKSIZE; i++) { - if (comp[i] != temp[i]) { + if (comp[i] != buf[i]) { break; } } + if (i != BLOCKSIZE) { break; } if (j > 0) { - if ((ret = __osPfsSelectBank(pfs, 0)) != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { return ret; } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, 0, temp)) != 0) { + + ret = __osContRamRead(pfs->queue, pfs->channel, 0, buf); + if (ret != 0) { return ret; } - if (temp[0] != 0x80) { + + if (buf[0] != 0x80) { break; } } @@ -85,8 +99,11 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) { j++; } while (j < PFS_MAX_BANKS); - if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { - return ret; + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { + return ret; + } } mask = (j > 0) ? 1 : 0; @@ -99,16 +116,21 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) { index[1] = PFS_ID_1AREA; index[2] = PFS_ID_2AREA; index[3] = PFS_ID_3AREA; + for (i = 0; i < 4; i++) { - if ((ret = __osContRamWrite(pfs->queue, pfs->channel, index[i], (u8*)newid, PFS_FORCE)) != 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, index[i], (u8*)newid, PFS_FORCE); + if (ret != 0) { return ret; } } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) { + + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, buf); + if (ret != 0) { return ret; } + for (i = 0; i < BLOCKSIZE; i++) { - if (temp[i] != *(u8*)((s32)newid + i)) { + if (buf[i] != *(u8*)((s32)newid + i)) { return PFS_ERR_DEVICE; } } @@ -123,8 +145,11 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) { s32 i; s32 j; - if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { - return ret; + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { + return ret; + } } index[0] = PFS_ID_0AREA; @@ -132,7 +157,8 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) { index[2] = PFS_ID_2AREA; index[3] = PFS_ID_3AREA; for (i = 1; i < 4; i++) { - if ((ret = __osContRamRead(pfs->queue, pfs->channel, index[i], (u8*)check)) != 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, index[i], (u8*)check); + if (ret != 0) { return ret; } __osIdCheckSum((u16*)check, &sum, &idSum); @@ -146,7 +172,8 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) { for (j = 0; j < 4; j++) { if (j != i) { - if ((ret = __osContRamWrite(pfs->queue, pfs->channel, index[j], (u8*)check, PFS_FORCE)) != 0) { + ret = __osContRamWrite(pfs->queue, pfs->channel, index[j], (u8*)check, PFS_FORCE); + if (ret != 0) { return ret; } } @@ -157,27 +184,30 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) { s32 __osGetId(OSPfs* pfs) { u16 sum; u16 isum; - u8 temp[BLOCKSIZE]; + u8 buf[BLOCKSIZE]; __OSPackId* id; __OSPackId newid; s32 ret; if (pfs->activebank != 0) { - if ((ret = __osPfsSelectBank(pfs, 0)) != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { return ret; } } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, buf); + if (ret != 0) { return ret; } - __osIdCheckSum((u16*)temp, &sum, &isum); - id = (__OSPackId*)temp; + __osIdCheckSum((u16*)buf, &sum, &isum); + id = (__OSPackId*)buf; if ((id->checksum != sum) || (id->invertedChecksum != isum)) { - if ((ret = __osCheckPackId(pfs, id)) == PFS_ERR_ID_FATAL) { + ret = __osCheckPackId(pfs, id); + if (ret == PFS_ERR_ID_FATAL) { ret = __osRepairPackId(pfs, id, &newid); - if (ret) { + if (ret != 0) { return ret; } id = &newid; @@ -186,13 +216,13 @@ s32 __osGetId(OSPfs* pfs) { } } - if ((id->deviceid & 0x01) == 0) { + if (!(id->deviceid & 1)) { ret = __osRepairPackId(pfs, id, &newid); if (ret) { return ret; } id = &newid; - if ((id->deviceid & 0x01) == 0) { + if (!(id->deviceid & 1)) { return PFS_ERR_DEVICE; } } @@ -210,7 +240,8 @@ s32 __osGetId(OSPfs* pfs) { pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE; pfs->dir_table = pfs->minode_table + (pfs->banks * PFS_ONE_PAGE); - if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label)) != 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_LABEL_AREA, pfs->label); + if (ret != 0) { return ret; } @@ -218,29 +249,32 @@ s32 __osGetId(OSPfs* pfs) { } s32 __osCheckId(OSPfs* pfs) { - u8 temp[BLOCKSIZE]; + u8 buf[BLOCKSIZE]; s32 ret; if (pfs->activebank != 0) { - ret = __osPfsSelectBank(pfs, 0); + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); if (ret == PFS_ERR_NEW_PACK) { - ret = __osPfsSelectBank(pfs, 0); + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); } if (ret != 0) { return ret; } } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) { + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, buf); + if (ret != 0) { if (ret != PFS_ERR_NEW_PACK) { return ret; } - if ((ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, temp)) != 0) { + + ret = __osContRamRead(pfs->queue, pfs->channel, PFS_ID_0AREA, buf); + if (ret != 0) { return ret; } } - if (bcmp(pfs->id, temp, BLOCKSIZE) != 0) { + if (bcmp(pfs->id, buf, BLOCKSIZE) != 0) { return PFS_ERR_NEW_PACK; } @@ -259,8 +293,11 @@ s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank) { return 0; } - if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { - return ret; + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { + return ret; + } } offset = ((bank > 0) ? 1 : pfs->inodeStartPage); diff --git a/src/libultra/io/pfschecker.c b/src/libultra/io/pfschecker.c index d42ac505ee..bf885a1a4b 100644 --- a/src/libultra/io/pfschecker.c +++ b/src/libultra/io/pfschecker.c @@ -1,7 +1,213 @@ +#include "PR/pfs.h" #include "global.h" -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfschecker/osPfsChecker.s") +#define CHECK_IPAGE(p) \ + (((p).ipage >= pfs->inodeStartPage) && ((p).inode_t.bank < pfs->banks) && ((p).inode_t.page >= 0x01) && \ + ((p).inode_t.page < 0x80)) -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfschecker/corrupted_init.s") +s32 corrupted_init(OSPfs* pfs, __OSInodeCache* cache); +s32 corrupted(OSPfs* pfs, __OSInodeUnit fpage, __OSInodeCache* cache); -#pragma GLOBAL_ASM("asm/non_matchings/boot/pfschecker/corrupted.s") +s32 osPfsChecker(OSPfs* pfs) { + s32 j; + s32 ret; + __OSInodeUnit next; + __OSInode checkedInode; + __OSInode tempInode; + __OSDir tempDir; + __OSInodeUnit nextNodeInFile[16]; + __OSInodeCache cache; + s32 fixed = 0; + u8 bank, prevBank = 254; + s32 cc, cl; + s32 offset; + + ret = __osCheckId(pfs); + if (ret == PFS_ERR_NEW_PACK) { + ret = __osGetId(pfs); + } + + if (ret != 0) { + return ret; + } + + ret = corrupted_init(pfs, &cache); + if (ret != 0) { + return ret; + } + + for (j = 0; j < pfs->dir_size; j++) { + ret = __osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir); + if (ret != 0) { + return ret; + } + + if ((tempDir.company_code != 0) || (tempDir.game_code != 0)) { + if ((tempDir.company_code == 0) || (tempDir.game_code == 0)) { + cc = -1; + } else { + next = tempDir.start_page; + cl = cc = 0; + bank = 255; + + while (CHECK_IPAGE(next)) { + if (bank != next.inode_t.bank) { + bank = next.inode_t.bank; + if (prevBank != bank) { + ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); + prevBank = bank; + } + + if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { + return ret; + } + } + + cc = corrupted(pfs, next, &cache) - cl; + if (cc != 0) { + break; + } + + cl = 1; + next = tempInode.inodePage[next.inode_t.page]; + } + } + + if ((cc != 0) || (next.ipage != PFS_EOF)) { + bzero(&tempDir, sizeof(__OSDir)); + if (pfs->activebank != 0) { + ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K); + if (ret != 0) { + return ret; + } + } + + ret = __osContRamWrite(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir, 0); + if (ret != 0) { + return ret; + } + + fixed++; + } + } + } + + for (j = 0; j < pfs->dir_size; j++) { + ret = __osContRamRead(pfs->queue, pfs->channel, pfs->dir_table + j, (u8*)&tempDir); + if (ret != 0) { + return ret; + } + + if ((tempDir.company_code != 0) && (tempDir.game_code != 0) && + (tempDir.start_page.ipage >= (u16)pfs->inodeStartPage)) { // cast required + nextNodeInFile[j].ipage = tempDir.start_page.ipage; + } else { + nextNodeInFile[j].ipage = 0; + } + } + + for (bank = 0; bank < pfs->banks; bank++) { + ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); + if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { + return (ret); + } + offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); + for (j = 0; j < offset; j++) { + checkedInode.inodePage[j].ipage = tempInode.inodePage[j].ipage; + } + for (; j < PFS_INODE_SIZE_PER_PAGE; j++) { + checkedInode.inodePage[j].ipage = PFS_PAGE_NOT_USED; + } + + for (j = 0; j < pfs->dir_size; j++) { + while (nextNodeInFile[j].inode_t.bank == bank && + nextNodeInFile[j].ipage >= (u16)pfs->inodeStartPage) { // cast required + u8 val = nextNodeInFile[j].inode_t.page; + + nextNodeInFile[j] = checkedInode.inodePage[val] = tempInode.inodePage[val]; + } + } + + ret = __osPfsRWInode(pfs, &checkedInode, PFS_WRITE, bank); + if (ret != 0) { + return ret; + } + } + + if (fixed != 0) { + pfs->status |= PFS_CORRUPTED; + } else { + pfs->status &= ~PFS_CORRUPTED; + } + + return 0; +} + +s32 corrupted_init(OSPfs* pfs, __OSInodeCache* cache) { + s32 i; + s32 n; + s32 offset; + u8 bank; + __OSInodeUnit tpage; + __OSInode tempInode; + s32 ret; + + for (i = 0; i < PFS_INODE_DIST_MAP; i++) { + cache->map[i] = 0; + } + cache->bank = 255; + + for (bank = PFS_ID_BANK_256K; bank < pfs->banks; bank++) { + offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); + ret = __osPfsRWInode(pfs, &tempInode, PFS_READ, bank); + if ((ret != 0) && (ret != PFS_ERR_INCONSISTENT)) { + return ret; + } + + for (i = offset; i < PFS_INODE_SIZE_PER_PAGE; i++) { + tpage = tempInode.inodePage[i]; + if ((tpage.ipage >= pfs->inodeStartPage) && (tpage.inode_t.bank != bank)) { + n = ((tpage.inode_t.page & 0x7F) / PFS_SECTOR_SIZE) + + PFS_SECTOR_PER_BANK * (tpage.inode_t.bank % PFS_BANK_LAPPED_BY); + cache->map[n] |= (1 << (bank % PFS_BANK_LAPPED_BY)); + } + } + } + return 0; +} + +s32 corrupted(OSPfs* pfs, __OSInodeUnit fpage, __OSInodeCache* cache) { + s32 j; + s32 n; + s32 hit = 0; + u8 bank; + s32 offset; + s32 ret = 0; + + n = (fpage.inode_t.page / PFS_SECTOR_SIZE) + PFS_SECTOR_PER_BANK * (fpage.inode_t.bank % PFS_BANK_LAPPED_BY); + + for (bank = PFS_ID_BANK_256K; bank < pfs->banks; bank++) { + offset = ((bank > PFS_ID_BANK_256K) ? 1 : pfs->inodeStartPage); + if ((bank == fpage.inode_t.bank) || (cache->map[n] & (1 << (bank % PFS_BANK_LAPPED_BY))) != 0) { + if (bank != cache->bank) { + ret = __osPfsRWInode(pfs, &(cache->inode), PFS_READ, bank); + if (ret && (ret != PFS_ERR_INCONSISTENT)) { + return ret; + } + cache->bank = bank; + } + + for (j = offset; ((hit < 2) && (j < PFS_INODE_SIZE_PER_PAGE)); j++) { + if (cache->inode.inodePage[j].ipage == fpage.ipage) { + hit++; + } + } + + if (hit >= 2) { + return 2; + } + } + } + + return hit; +}