/* 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;
}