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];
} __OSInodeCache; // size = 0x202
s32 __osGetId(OSPfs* pfs);
s32 osPfsChecker(OSPfs* pfs);
#endif

View File

@ -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);

View File

@ -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);

View File

@ -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;
}