/* Copyright (C) 2008 Emmanuel Varoquaux This file is part of XOS. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "vfat_fat_info.h" #include int init_fat_info(struct vfat_fat_info_struct *fat_info, const void *buf) { memcpy(&fat_info->boot_sect, buf, sizeof (bootSector_t)); if (fat_info->boot_sect.BPB_BytsPerSec != 512 && fat_info->boot_sect.BPB_BytsPerSec != 1024 && fat_info->boot_sect.BPB_BytsPerSec != 2048 && fat_info->boot_sect.BPB_BytsPerSec != 4096) return 0; if (fat_info->boot_sect.BPB_SecPerClus != 1 && fat_info->boot_sect.BPB_SecPerClus != 2 && fat_info->boot_sect.BPB_SecPerClus != 4 && fat_info->boot_sect.BPB_SecPerClus != 8 && fat_info->boot_sect.BPB_SecPerClus != 16 && fat_info->boot_sect.BPB_SecPerClus != 32 && fat_info->boot_sect.BPB_SecPerClus != 64 && fat_info->boot_sect.BPB_SecPerClus != 128) return 0; if (fat_info->boot_sect.BPB_ResvdSecCnt == 0) return 0; if (fat_info->boot_sect.BPB_NumFATs < 1) return 0; fat_info->RootDirSectors = ((fat_info->boot_sect.BPB_RootEntCnt * 32) + (fat_info->boot_sect.BPB_BytsPerSec - 1)) / fat_info->boot_sect.BPB_BytsPerSec; if (fat_info->boot_sect.BPB_FATSz16 != 0) fat_info->FATSz = fat_info->boot_sect.BPB_FATSz16; else fat_info->FATSz = fat_info->boot_sect.fat32.BPB_FATSz32; if (fat_info->boot_sect.BPB_TotSec16 != 0) fat_info->TotSec = fat_info->boot_sect.BPB_TotSec16; else fat_info->TotSec = fat_info->boot_sect.BPB_TotSec32; fat_info->FirstDataSector = fat_info->boot_sect.BPB_ResvdSecCnt + (fat_info->boot_sect.BPB_NumFATs * fat_info->FATSz) + fat_info->RootDirSectors; fat_info->DataSec = fat_info->TotSec - (fat_info->boot_sect.BPB_ResvdSecCnt + (fat_info->boot_sect.BPB_NumFATs * fat_info->FATSz) + fat_info->RootDirSectors); fat_info->CountofClusters = fat_info->DataSec / fat_info->boot_sect.BPB_SecPerClus; if (fat_info->CountofClusters < 4085) fat_info->FATType = FAT12; /* Volume is FAT12 */ else if (fat_info->CountofClusters < 65525) fat_info->FATType = FAT16; /* Volume is FAT16 */ else fat_info->FATType = FAT32; /* Volume is FAT32 */ if (fat_info->FATType == FAT32 && fat_info->boot_sect.BPB_RootEntCnt != 0) return 0; if (fat_info->boot_sect.BPB_TotSec16 == 0 && fat_info->boot_sect.BPB_TotSec32 == 0) return 0; if (fat_info->FATType == FAT32 && fat_info->boot_sect.BPB_TotSec16 != 0) return 0; if (fat_info->boot_sect.BPB_Media != 0xf0 && fat_info->boot_sect.BPB_Media != 0xf8 && fat_info->boot_sect.BPB_Media != 0xf9 && fat_info->boot_sect.BPB_Media != 0xfa && fat_info->boot_sect.BPB_Media != 0xfb && fat_info->boot_sect.BPB_Media != 0xfc && fat_info->boot_sect.BPB_Media != 0xfd && fat_info->boot_sect.BPB_Media != 0xfe && fat_info->boot_sect.BPB_Media != 0xff) return 0; if (fat_info->FATType == FAT32 && fat_info->boot_sect.BPB_FATSz16 != 0) return 0; if (fat_info->FATType == FAT32 && fat_info->boot_sect.BPB_TotSec32 == 0) return 0; if (fat_info->FATType == FAT12 || fat_info->FATType == FAT16) fat_info->FirstRootDirSecNum = fat_info->boot_sect.BPB_ResvdSecCnt + (fat_info->boot_sect.BPB_NumFATs * fat_info->boot_sect.BPB_FATSz16); return 1; } /* SecBuff doit contenir deux secteurs. */ unsigned long get_FATClusEntryVal(const unsigned char SecBuff[], const struct vfat_fat_info_struct *fat_info, unsigned long N) { unsigned long FATClusEntryVal; if (fat_info->FATType == FAT12) { FATClusEntryVal = *((const WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]); if (N & 0x0001) return FATClusEntryVal >> 4; /* Cluster number is ODD */ else return FATClusEntryVal & 0x0fff; /* Cluster number is EVEN */ } else if (fat_info->FATType == FAT16) return *((const WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]); else return (*((const DWORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) & 0x0fffffff; } /* SecBuff doit contenir deux secteurs. */ void set_FATClusEntryVal(unsigned char SecBuff[], const struct vfat_fat_info_struct *fat_info, unsigned long N, unsigned long FATClusEntryVal) { if (fat_info->FATType == FAT12) { if (N & 0x0001) { FATClusEntryVal = FATClusEntryVal << 4; /* Cluster number is ODD */ *((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = (*((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) & 0x000f; } else { FATClusEntryVal = FATClusEntryVal & 0x0fff; /* Cluster number is EVEN */ *((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = (*((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) & 0xf000; } *((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = (*((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) | FATClusEntryVal; } else if (fat_info->FATType == FAT16) *((WORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = FATClusEntryVal; else { FATClusEntryVal = FATClusEntryVal & 0x0fffffff; *((DWORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = (*((DWORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) & 0xf0000000; *((DWORD *)&SecBuff[ThisFATEntOffset(fat_info, N)]) = (*((DWORD *)&SecBuff[ThisFATEntOffset(fat_info, N)])) | FATClusEntryVal; } } int IsEOF(const struct vfat_fat_info_struct *fat_info, unsigned long FATContent) { if (fat_info->FATType == FAT12) { if (FATContent >= 0x0ff8) return TRUE; } else if (fat_info->FATType == FAT16) { if (FATContent >= 0xfff8) return TRUE; } else { if (FATContent >= 0x0ffffff8) return TRUE; } return FALSE; }