View of xos/fs/vfat_fat_info.c


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */
 
#include "vfat_fat_info.h"
 
#include <string.h>
 
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;
}