public bool VerifyFsChecksum(iQueFsHeader fatHeader, int fatBlockIdx) { io.Stream.Position = (fatBlockIdx * BLOCK_SZ); ushort sum = 0; for (int i = 0; i < 0x1FFF; i++) { sum += io.Reader.ReadUInt16().EndianSwap(); } sum += fatHeader.CheckSum; // should be EndianSwap'd already by ReadFilesystem return(sum == 0xCAD7); }
private bool ReadFilesystem() { FsHeaders = new List <iQueFsHeader>(); FsBlocks = new List <int>(); FsBadBlocks = new List <int>(); FsInodes = new List <List <iQueFsInode> >(); FsAllocationTables = new List <List <short> >(); int latestSeqNo = -1; for (int i = 0; i < NUM_FAT_BLOCKS; i++) { var blockNum = (NUM_BLOCKS_IN_FAT - 1) - i; // read FAT area from end to beginning SeekToBlock(blockNum); io.Stream.Position += FS_HEADER_ADDR; var header = io.Reader.ReadStruct <iQueFsHeader>(); header.EndianSwap(); if (header.Magic != MAGIC_BBFS) // todo: && header.Magic != MAGIC_BBFL, once we know what BBFL/"linked fats" actually are { continue; } if (!SkipVerifyFsChecksums && InodesOffset == 0) // only care about fs checksum if this is a proper dump and we aren't using hacky InodesOffset hack { if (!VerifyFsChecksum(header, blockNum)) { FsBadBlocks.Add(blockNum); continue; // bad FS checksum :( } } FsHeaders.Add(header); FsBlocks.Add(blockNum); if (header.SeqNo > latestSeqNo) { MainFs = header; MainFsBlock = blockNum; MainFsIndex = FsHeaders.Count - 1; latestSeqNo = header.SeqNo; } io.Stream.Position = blockNum * BLOCK_SZ; var allocTable = new List <short>(); for (int y = 0; y < NUM_BLOCKS_IN_FAT; y++) { allocTable.Add((short)(io.Reader.ReadUInt16().EndianSwap())); } int numEntries = NUM_FS_ENTRIES; if (InodesOffset > 0) { io.Stream.Position += InodesOffset; // skip weird truncated inode if needed numEntries--; // and now we'll have to read one less entry } // now begin reading inodes var inodes = new List <iQueFsInode>(); for (int y = 0; y < numEntries; y++) { var inode = io.Reader.ReadStruct <iQueFsInode>(); inode.EndianSwap(); inodes.Add(inode); } FsAllocationTables.Add(allocTable); FsInodes.Add(inodes); } return(latestSeqNo >= 0); }