The Pedigree Project 0.1
FatFilesystem-fsinfo.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include "pedigree/kernel/syscallError.h"
9
10#include "FatFilesystem.h"
11
12bool FatFilesystem::invalidateFsInfoHints() {
13 if (m_Type != FAT32 || m_FsInfoInvalidated)
14 return true;
15
16 const uint32_t sectorBytes = LITTLE_TO_HOST16(m_Superblock.BPB_BytsPerSec);
17 const uint32_t reservedSectors = LITTLE_TO_HOST16(m_Superblock.BPB_RsvdSecCnt);
18 const uint32_t primary = LITTLE_TO_HOST16(m_Superblock32.BPB_FsInfo);
19 if (sectorBytes < sizeof(FSInfo32) || !primary || primary >= reservedSectors)
20 return true;
21
22 const uint32_t backupBoot = LITTLE_TO_HOST16(m_Superblock32.BPB_BkBootSec);
23 const uint32_t sectors[] = {primary, primary + backupBoot};
24 const size_t copies =
25 backupBoot && backupBoot < reservedSectors && sectors[1] < reservedSectors ? 2 : 1;
26 uint8_t* bytes = new uint8_t[sectorBytes];
27 if (!bytes) {
28 SYSCALL_ERROR(OutOfMemory);
29 return false;
30 }
31 for (size_t i = 0; i < copies; ++i) {
32 if (!readSectorBlock(sectors[i], sectorBytes, reinterpret_cast<uintptr_t>(bytes))) {
33 delete[] bytes;
34 SYSCALL_ERROR(IoError);
35 return false;
36 }
37
38 FSInfo32* info = reinterpret_cast<FSInfo32*>(bytes);
39 if (LITTLE_TO_HOST32(info->FSI_LeadSig) != 0x41615252 ||
40 LITTLE_TO_HOST32(info->FSI_StrucSig) != 0x61417272 ||
41 LITTLE_TO_HOST32(info->FSI_TrailSig) != 0xAA550000)
42 continue;
43
44 // Rewrite even unknown hints: a failed flush may have changed only the disk cache.
45 info->FSI_Free_Count = HOST_TO_LITTLE32(0xFFFFFFFFU);
46 info->FSI_NxtFree = HOST_TO_LITTLE32(0xFFFFFFFFU);
47 if (!writeSectorBlock(sectors[i], sectorBytes, reinterpret_cast<uintptr_t>(bytes))) {
48 delete[] bytes;
49 SYSCALL_ERROR(IoError);
50 return false;
51 }
52 }
53 delete[] bytes;
54 m_FsInfoInvalidated = true;
55 return true;
56}
bool writeSectorBlock(uint32_t sec, size_t size, uintptr_t buffer)
bool readSectorBlock(uint32_t sec, size_t size, uintptr_t buffer) const
Superblock m_Superblock
Definition fat.h:91