summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEllipticEllipsis <73679967+EllipticEllipsis@users.noreply.github.com>2021-11-11 15:29:22 +0000
committerGitHub <noreply@github.com>2021-11-11 12:29:22 -0300
commit2e5c142f3b66e5bca3646fa9635ed06ec6d59a30 (patch)
treecd68d4ae66bd0372cb9954cdd1c5cfe0a6978917 /src
parentd825ef5de1ea0c99336a43cc3ed573bf4323a2c0 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/libultra/io/contpfs.c117
-rw-r--r--src/libultra/io/pfschecker.c212
2 files changed, 286 insertions, 43 deletions
diff --git a/src/libultra/io/contpfs.c b/src/libultra/io/contpfs.c
index 42009674f..3dd0c96ca 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 d42ac505e..bf885a1a4 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;
+}