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>
This commit is contained in:
EllipticEllipsis 2021-11-11 15:29:22 +00:00 committed by GitHub
parent d825ef5de1
commit 2e5c142f3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 289 additions and 46 deletions

View File

@ -134,4 +134,7 @@ typedef struct {
/* 0x101 */ u8 map[PFS_INODE_DIST_MAP]; /* 0x101 */ u8 map[PFS_INODE_DIST_MAP];
} __OSInodeCache; // size = 0x202 } __OSInodeCache; // size = 0x202
s32 __osGetId(OSPfs* pfs);
s32 osPfsChecker(OSPfs* pfs);
#endif #endif

View File

@ -332,7 +332,6 @@ u16 __osSumcalc(u8* ptr, s32 length);
s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum); s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum);
s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid); s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid);
// void __osCheckPackId(void); // void __osCheckPackId(void);
// void __osGetId(void);
s32 __osCheckId(OSPfs* pfs); s32 __osCheckId(OSPfs* pfs);
s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank); s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank);
u32 osGetCount(void); u32 osGetCount(void);
@ -427,8 +426,6 @@ u32 __osGetFpcCsr(void);
// void osPfsInitPak(void); // void osPfsInitPak(void);
// void __osPfsCheckRamArea(void); // void __osPfsCheckRamArea(void);
// void osPfsChecker(void); // void osPfsChecker(void);
// void corrupted_init(void);
// void corrupted(void);
u32 osAiGetLength(void); u32 osAiGetLength(void);
s32 osEPiWriteIo(OSPiHandle* pihandle, u32 devAddr, u32 data); s32 osEPiWriteIo(OSPiHandle* pihandle, u32 devAddr, u32 data);
void osMapTLBRdb(void); void osMapTLBRdb(void);

View File

@ -27,7 +27,7 @@ s32 __osIdCheckSum(u16* ptr, u16* checkSum, u16* idSum) {
s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) { s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) {
s32 ret = 0; s32 ret = 0;
u8 temp[BLOCKSIZE]; u8 buf[BLOCKSIZE];
u8 comp[BLOCKSIZE]; u8 comp[BLOCKSIZE];
u8 mask = 0; u8 mask = 0;
s32 i, j = 0; s32 i, j = 0;
@ -38,46 +38,60 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) {
newid->serialMid = badid->serialMid; newid->serialMid = badid->serialMid;
newid->serialLow = badid->serialLow; newid->serialLow = badid->serialLow;
if ((pfs->activebank != 0) && ((ret = __osPfsSelectBank(pfs, 0)) != 0)) { if (pfs->activebank != 0) {
return ret; ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret;
}
} }
do { do {
if ((ret = __osPfsSelectBank(pfs, j)) != 0) { ret = __osPfsSelectBank(pfs, j);
if (ret != 0) {
return ret; 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; return ret;
} }
temp[0] = j | 0x80; buf[0] = j | 0x80;
for (i = 1; i < BLOCKSIZE; i++) { 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; 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); return (ret);
} }
for (i = 0; i < BLOCKSIZE; i++) { for (i = 0; i < BLOCKSIZE; i++) {
if (comp[i] != temp[i]) { if (comp[i] != buf[i]) {
break; break;
} }
} }
if (i != BLOCKSIZE) { if (i != BLOCKSIZE) {
break; break;
} }
if (j > 0) { if (j > 0) {
if ((ret = __osPfsSelectBank(pfs, 0)) != 0) { ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret; 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; return ret;
} }
if (temp[0] != 0x80) {
if (buf[0] != 0x80) {
break; break;
} }
} }
@ -85,8 +99,11 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) {
j++; j++;
} while (j < PFS_MAX_BANKS); } while (j < PFS_MAX_BANKS);
if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { if (pfs->activebank != 0) {
return ret; ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret;
}
} }
mask = (j > 0) ? 1 : 0; mask = (j > 0) ? 1 : 0;
@ -99,16 +116,21 @@ s32 __osRepairPackId(OSPfs* pfs, __OSPackId* badid, __OSPackId* newid) {
index[1] = PFS_ID_1AREA; index[1] = PFS_ID_1AREA;
index[2] = PFS_ID_2AREA; index[2] = PFS_ID_2AREA;
index[3] = PFS_ID_3AREA; index[3] = PFS_ID_3AREA;
for (i = 0; i < 4; i++) { 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; 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; return ret;
} }
for (i = 0; i < BLOCKSIZE; i++) { for (i = 0; i < BLOCKSIZE; i++) {
if (temp[i] != *(u8*)((s32)newid + i)) { if (buf[i] != *(u8*)((s32)newid + i)) {
return PFS_ERR_DEVICE; return PFS_ERR_DEVICE;
} }
} }
@ -123,8 +145,11 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) {
s32 i; s32 i;
s32 j; s32 j;
if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { if (pfs->activebank != 0) {
return ret; ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret;
}
} }
index[0] = PFS_ID_0AREA; index[0] = PFS_ID_0AREA;
@ -132,7 +157,8 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) {
index[2] = PFS_ID_2AREA; index[2] = PFS_ID_2AREA;
index[3] = PFS_ID_3AREA; index[3] = PFS_ID_3AREA;
for (i = 1; i < 4; i++) { 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; return ret;
} }
__osIdCheckSum((u16*)check, &sum, &idSum); __osIdCheckSum((u16*)check, &sum, &idSum);
@ -146,7 +172,8 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) {
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
if (j != i) { 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; return ret;
} }
} }
@ -157,27 +184,30 @@ s32 __osCheckPackId(OSPfs* pfs, __OSPackId* check) {
s32 __osGetId(OSPfs* pfs) { s32 __osGetId(OSPfs* pfs) {
u16 sum; u16 sum;
u16 isum; u16 isum;
u8 temp[BLOCKSIZE]; u8 buf[BLOCKSIZE];
__OSPackId* id; __OSPackId* id;
__OSPackId newid; __OSPackId newid;
s32 ret; s32 ret;
if (pfs->activebank != 0) { if (pfs->activebank != 0) {
if ((ret = __osPfsSelectBank(pfs, 0)) != 0) { ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret; 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; return ret;
} }
__osIdCheckSum((u16*)temp, &sum, &isum); __osIdCheckSum((u16*)buf, &sum, &isum);
id = (__OSPackId*)temp; id = (__OSPackId*)buf;
if ((id->checksum != sum) || (id->invertedChecksum != isum)) { 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); ret = __osRepairPackId(pfs, id, &newid);
if (ret) { if (ret != 0) {
return ret; return ret;
} }
id = &newid; id = &newid;
@ -186,13 +216,13 @@ s32 __osGetId(OSPfs* pfs) {
} }
} }
if ((id->deviceid & 0x01) == 0) { if (!(id->deviceid & 1)) {
ret = __osRepairPackId(pfs, id, &newid); ret = __osRepairPackId(pfs, id, &newid);
if (ret) { if (ret) {
return ret; return ret;
} }
id = &newid; id = &newid;
if ((id->deviceid & 0x01) == 0) { if (!(id->deviceid & 1)) {
return PFS_ERR_DEVICE; return PFS_ERR_DEVICE;
} }
} }
@ -210,7 +240,8 @@ s32 __osGetId(OSPfs* pfs) {
pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE; pfs->minode_table = (1 + pfs->banks) * PFS_ONE_PAGE;
pfs->dir_table = pfs->minode_table + (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; return ret;
} }
@ -218,29 +249,32 @@ s32 __osGetId(OSPfs* pfs) {
} }
s32 __osCheckId(OSPfs* pfs) { s32 __osCheckId(OSPfs* pfs) {
u8 temp[BLOCKSIZE]; u8 buf[BLOCKSIZE];
s32 ret; s32 ret;
if (pfs->activebank != 0) { if (pfs->activebank != 0) {
ret = __osPfsSelectBank(pfs, 0); ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret == PFS_ERR_NEW_PACK) { if (ret == PFS_ERR_NEW_PACK) {
ret = __osPfsSelectBank(pfs, 0); ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
} }
if (ret != 0) { if (ret != 0) {
return ret; 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) { if (ret != PFS_ERR_NEW_PACK) {
return ret; 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; return ret;
} }
} }
if (bcmp(pfs->id, temp, BLOCKSIZE) != 0) { if (bcmp(pfs->id, buf, BLOCKSIZE) != 0) {
return PFS_ERR_NEW_PACK; return PFS_ERR_NEW_PACK;
} }
@ -259,8 +293,11 @@ s32 __osPfsRWInode(OSPfs* pfs, __OSInode* inode, u8 flag, u8 bank) {
return 0; return 0;
} }
if ((pfs->activebank != 0) && (ret = __osPfsSelectBank(pfs, 0)) != 0) { if (pfs->activebank != 0) {
return ret; ret = __osPfsSelectBank(pfs, PFS_ID_BANK_256K);
if (ret != 0) {
return ret;
}
} }
offset = ((bank > 0) ? 1 : pfs->inodeStartPage); offset = ((bank > 0) ? 1 : pfs->inodeStartPage);

View File

@ -1,7 +1,213 @@
#include "PR/pfs.h"
#include "global.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;
}