Add IVFC parser

This commit is contained in:
offtkp 2023-07-28 19:54:18 +03:00
parent 72b45377e1
commit f3ce29bf2d
5 changed files with 137 additions and 1 deletions

78
src/core/fs/ivfc.cpp Normal file
View file

@ -0,0 +1,78 @@
#include "fs/ivfc.hpp"
namespace IVFC {
size_t parseIVFC(uintptr_t ivfcStart, IVFC& ivfc) {
uintptr_t ivfcPointer = ivfcStart;
std::string magicIVFC((char*)ivfcPointer, 4);
ivfcPointer += 4;
if (magicIVFC != "IVFC") {
printf("Invalid IVFC magic: %s\n", magicIVFC.c_str());
return 0;
}
uint32_t magicIdentifier = *(u32*)ivfcPointer;
ivfcPointer += 4;
// RomFS IVFC uses 0x10000, DISA/DIFF IVFC uses 0x20000 here
if (magicIdentifier != 0x10000 && magicIdentifier != 0x20000) {
printf("Invalid IVFC magic identifier: %08X\n", magicIdentifier);
return 0;
}
if (magicIdentifier == 0x10000) {
ivfc.masterHashSize = *(u32*)ivfcPointer;
ivfcPointer += 4;
// RomFS IVFC uses 3 levels
ivfc.levels.resize(3);
} else {
ivfc.masterHashSize = *(u64*)ivfcPointer;
ivfcPointer += 8;
// DISA/DIFF IVFC uses 4 levels
ivfc.levels.resize(4);
}
for (size_t i = 0; i < ivfc.levels.size(); i++) {
IVFCLevel level;
level.logicalOffset = *(u64*)ivfcPointer;
ivfcPointer += 8;
level.size = *(u64*)ivfcPointer;
ivfcPointer += 8;
// This field is in log2
level.blockSize = 1 << *(u32*)ivfcPointer;
ivfcPointer += 4;
// Skip 4 reserved bytes
ivfcPointer += 4;
ivfc.levels[i] = level;
}
u64 ivfcDescriptorSize = *(u64*)ivfcPointer;
ivfcPointer += 8;
uintptr_t ivfcActualSize = ivfcPointer - ivfcStart;
// According to 3DBrew, this is usually the case but not guaranteed
if (ivfcActualSize != ivfcDescriptorSize) {
printf("IVFC descriptor size mismatch: %lx != %lx\n", ivfcActualSize, ivfcDescriptorSize);
}
if (magicIdentifier == 0x10000 && ivfcActualSize != 0x5C) {
// This is always 0x5C bytes long
printf("Invalid IVFC size: %08x\n", (u32)ivfcActualSize);
return 0;
} else if (magicIdentifier == 0x20000 && ivfcActualSize != 0x78) {
// This is always 0x78 bytes long
printf("Invalid IVFC size: %08x\n", (u32)ivfcActualSize);
return 0;
}
return ivfcActualSize;
}
} // namespace IVFC

21
src/core/fs/romfs.cpp Normal file
View file

@ -0,0 +1,21 @@
#include "fs/romfs.hpp"
#include "fs/ivfc.hpp"
#include <cstdio>
namespace RomFS {
RomFSNode parseRomFSTree(uintptr_t romFS, u64 romFSSize) {
RomFSNode root;
IVFC::IVFC ivfc;
size_t ivfcSize = IVFC::parseIVFC((uintptr_t)romFS, ivfc);
if (ivfcSize == 0) {
printf("Failed to parse IVFC\n");
return {};
}
return root;
}
} // namespace RomFS