?? fat_layer.c
字號:
/*
* BETA API for FATFS
* No implementation for multiple filehandles
* Buffers are the same size as the sectors on the disk
* No long filename support...
*/
#include "fat_layer.h"
#include "ideutils.h"
#include "system.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#ifndef NULL
#define NULL 0
#endif
#define DEBUG_FILE_SEEK FALSE
#if FAT_DEBUG
void debug_printBpbFat(BPB_FAT_PTR bpb_fat_ptr);
#endif
/* These should, undoubtedly, be broken out into function pointers... */
int fatReadLogicalSector(LONG sector, LONG num_sectors, BYTE *buf){
// if(num_sectors != 1)
// return IDE_OP_ERROR;
if(readLogicalSector(sector, num_sectors, (unsigned short *)buf) != 1)
return IDE_OP_ERROR;
return(IDE_OP_OK);
}
int fatWriteLogicalSector(LONG sector, LONG num_sectors, BYTE *buf){
if(num_sectors != 1)
return IDE_OP_ERROR;
if(writeLogicalSector(sector, num_sectors, (unsigned short *)buf) != 1)
return IDE_OP_ERROR;
return(IDE_OP_OK);
}
#define DEBUG_DOFATTABLEOP FALSE
int doFatTableOp(VOLUME_PTR vol){
unsigned int *fat_entry_ptr;
LONG new_fat_sec;
LONG fat_offset;
/*
* Calculate FAT operation
*/
/* Is the FAT buffer in range? */
/* Calculation is more complex for FAT12 */
if (vol->fat_type == FAT12)
new_fat_sec = vol->bpb_sector_offset + vol->bpb_fat_ptr->rsvd_sec_cnt +
(((LONG)vol->fat_num + ((vol->fat_num)/2)) / vol->fat_bytes_per_sec);
else /* FAT16 or FAT32 */
new_fat_sec = vol->bpb_sector_offset + vol->bpb_fat_ptr->rsvd_sec_cnt +
(((LONG)vol->fat_num * vol->fat_entry_size) / vol->fat_bytes_per_sec);
#if FAT_DEBUG
if(DEBUG_DOFATTABLEOP){
printf("doFatTableOp:\n");
printf("rsvd_sec_cnt: %x, fat_num: %x, entry_size: %x, fat_bytes_per_sec: %x\n",
vol->bpb_fat_ptr->rsvd_sec_cnt,
(LONG)vol->fat_num,
vol->fat_entry_size,
vol->fat_bytes_per_sec);
}
#endif
if(new_fat_sec != vol->fat_sector){
if((vol->fat_op != FAT_RESET) && (vol->fat_buf_status == FAT_DIRTY))
fatWriteLogicalSector(vol->fat_sector, 1, vol->fat_buf_ptr);
vol->fat_sector = new_fat_sec;
/*
* When handling FAT12: read two sectors of FAT table
* just so that we don't have to dela with the "over the sector border"
* problem.
*/
if (vol->fat_type == FAT12)
fatReadLogicalSector(vol->fat_sector, 2, vol->fat_buf_ptr);
else
fatReadLogicalSector(vol->fat_sector, 1, vol->fat_buf_ptr);
vol->fat_buf_status &= ~FAT_DIRTY;
}
if (vol->fat_type == FAT12)
fat_offset = ((LONG)vol->fat_num + ((vol->fat_num)/2)) % vol->fat_bytes_per_sec;
else
fat_offset = ((LONG)vol->fat_num /** vol->fat_entry_size*/) % vol->fat_bytes_per_sec;
vol->fat_data = 0;
/* Do the operation */
if(vol->fat_op == FAT_GET){
if(vol->fat_type == FAT12){
vol->fat_data = *((BYTE*)(vol->fat_buf_ptr + fat_offset)) |
((*((BYTE*)(vol->fat_buf_ptr + fat_offset + 1)))<<8);
}else if(vol->fat_type == FAT16 ){
vol->fat_data = *((unsigned short*)(vol->fat_buf_ptr + (fat_offset)));
}else if(vol->fat_type == FAT32){
vol->fat_data = *((unsigned int*)(vol->fat_buf_ptr + fat_offset)) & 0x0fffffff;
}
}else if (vol->fat_op == FAT_SET){
if(vol->fat_type == FAT16 || vol->fat_type == FAT12){
*((unsigned short*)(vol->fat_buf_ptr + fat_offset)) = (unsigned short)vol->fat_data ;
}else if(vol->fat_type == FAT32){
vol->fat_data |= (*((unsigned int*)(vol->fat_buf_ptr + fat_offset)) & 0xf0000000);
*((unsigned short*)(vol->fat_buf_ptr + fat_offset)) = vol->fat_data;
}
vol->fat_buf_status |= FAT_DIRTY;
}else return UNKNOWN_FAT_OP;
/* Twelve o'clock and all is well... Return, well, nothing. */
return(0);
}
#if FAT_DEBUG
char debug_nibbleToChar(BYTE c){
char ret=0;
if(c <= 9){
ret = '0' + c;
}else if((10 <= c) && (c <= 15)){
ret = 'A' + (c-10);
}
return ret;
}
#endif
#if FAT_DEBUG
#define DEBUG_PRINT_DELAY 10000
void debug_print(BYTE *buffer, int num_bytes){
int i,j,k;
BYTE c;
char hn, ln;
for(i=0;i<num_bytes;i++){
c = *((BYTE *)buffer+i);
hn = debug_nibbleToChar(0x0F & (c>>4));
ln = debug_nibbleToChar(0x0F & c);
// if(num_bytes%16 == 0) printf("\n\n%x: ", i);
printf("%c%c ", hn, ln);
if((i % 16) == 0)
printf("\n");
for(j=0;j<DEBUG_PRINT_DELAY;){
j++;
}
}
}
#endif
int determineFatType(VOLUME_PTR vol){
/* This is according to the Microsoft White paper */
if (vol->count_of_clusters < 4085) /* FAT12 */
{
vol->fat_type = FAT12;
}else if (vol->count_of_clusters < 65525) /* FAT16 */
{
vol->fat_type = FAT12;
}else
{
vol->fat_type = FAT32;
}
return vol->fat_type;
};
/* The global file pointer */
VOLUME_PTR _global_volume_ptr=NULL;
FILE_HNDL_PTR file_handle_array[NUM_FS_HANDLES];
FILE_HNDL_PTR doFileHndlInit(int some_number)
{
FILE_HNDL_PTR file_ptr;
file_ptr = (FILE_HNDL_PTR)malloc(sizeof(FILE_HNDL));
file_ptr->dir_entry=(FAT_FILE_PTR)malloc(sizeof(FAT_FILE));
file_ptr->fat_file_buf=(BYTE *)malloc(sizeof(BYTE) * 512);
/* Modded for speed */
file_ptr->vol_ptr = _global_volume_ptr;
// file_ptr->vol_ptr = (VOLUME_PTR)doFatInit();
return(file_ptr);
}
FILE_HNDL_PTR get_file_handle(void){
FILE_HNDL_PTR file_hndl;
/*
* To Do:
* Make this routine actually work with more
* than one filehandle
*/
file_hndl = doFileHndlInit(0);
file_handle_array[0] = file_hndl;
return(file_hndl);
}
VOLUME_PTR doFatInit()
{
VOLUME_PTR vol;
/* Allocate memory for the volume desciption structure */
vol = (VOLUME_PTR)malloc(sizeof(VOLUME));
vol->bpb_fat_ptr = (BPB_FAT_PTR)malloc(sizeof(BPB_FAT));
vol->bpb_fat_offset_ptr = (BPB_FAT_OFFSET_PTR)malloc(sizeof(BPB_FAT_OFFSET));
/*
* Allocate a scratch buffer of size two sectors in case we are handling
* a FAT12 file system (not having to worry about sectors borders
*/
vol->fat_buf_ptr = (FAT_SEC_BUF)malloc(sizeof(BYTE) * 512 * 2);
vol->bpb_sector_offset = 32;
int i;
/* Run through the IDE initialization routines... */
IDE_setVerbosity(0);
if(IDE_initialize()){
// printf("IDE init: PASS\n");
}else{
// printf("IDE init: FAIL\n");
return( NULL );
};
/*
* This may need to change according to where the BPB fat can be
* Right now, I donna' know.
*/
/* Look fot the bpb and set the bpb sector offset */
for (i=0; i<256; i++)
{
fatReadLogicalSector(i,1,vol->fat_buf_ptr);
if (vol->fat_buf_ptr[510] == 0x55 && vol->fat_buf_ptr[511] == 0xaa &&
(vol->fat_buf_ptr[0] == 0xeb || vol->fat_buf_ptr[0] == 0xe9))
{
vol->bpb_sector_offset = i;
// printf("Found the bpb at sector number %d\n",i);
break;
}
if (i == 255)
{
printf("Can't find fat boot sector. Exiting ...\n");
return 0;
}
}
#if FAT_DEBUG
// debug_print(vol->fat_buf_ptr, sizeof(BPB_FAT));
#endif
/* Manually copy over all data for BPB_FAT */
memcpy((BYTE*)vol->bpb_fat_ptr, (BYTE*)vol->fat_buf_ptr, sizeof(BPB_FAT));
#if FAT_DEBUG
// debug_print((char*)vol->bpb_fat_ptr, sizeof(BPB_FAT));
// printSectorBuffer(1,(unsigned short *)vol->bpb_fat_ptr);
#endif
/* Do some calculations based on the values read from the device */
/*
* 1. the number of sectors the root dir occupies
* The "complicated" calculation is because we want to round up
*/
vol->root_sectors = ((vol->bpb_fat_ptr->root_ent_cnt * 32)+(vol->bpb_fat_ptr->bytes_per_sec)-1)
/(vol->bpb_fat_ptr->bytes_per_sec);
/* 2. The Count of Clusters */
vol->count_of_clusters = vol->fat_data_sector / vol->bpb_fat_ptr->bytes_per_sec;
determineFatType(vol);
/* Occupy the data structure at offset 36
* don't do anything with FAT32 at the moment. */
memcpy((BYTE*)vol->bpb_fat_offset_ptr, (BYTE*)vol->fat_buf_ptr + 36, sizeof(BPB_FAT_OFFSET));
if(vol->fat_type == FAT16 || vol->fat_type == FAT12){
vol->fat_size=((LONG)vol->bpb_fat_ptr->fat_size_16);
vol->fat_entry_size=2;
vol->fat_bytes_per_sec=((LONG)vol->bpb_fat_ptr->bytes_per_sec);
vol->root_sector = vol->bpb_fat_ptr->rsvd_sec_cnt +
(vol->bpb_fat_ptr->num_fats * vol->bpb_fat_ptr->fat_size_16) +
vol->bpb_sector_offset;
vol->fat_data_sector=((LONG)vol->bpb_fat_ptr->rsvd_sec_cnt +
(vol->root_sectors) +
(vol->bpb_fat_ptr->num_fats * vol->bpb_fat_ptr->fat_size_16)) +
vol->bpb_sector_offset;
}
/* Setup the status of the FAT table */
vol->fat_buf_status = FAT_NULL_CONDITION;
/*
* To do: add FAT32 here
*/
/* Initialize struct */
vol->fat_sector = 0;
#if FAT_DEBUG
debug_printBpbFat(vol->bpb_fat_ptr);
#endif
_global_volume_ptr = vol;
return vol;
}
#if FAT_DEBUG
void debug_volume(VOLUME_PTR vol){
printf("fat_entry_size: %ld\n",vol->fat_entry_size);
printf("fat_bytes_per_sec: %ld\n",vol->fat_bytes_per_sec);
printf("fat_size: %ld\n",vol->fat_size);
printf("root_sector: %ld\n",vol->root_sector);
printf("fat_data_sector: %ld\n",vol->fat_data_sector);
printf("root_sectors: %ld\n",vol->root_sectors);
}
#endif
#if FAT_DEBUG
void debug_printFatFileStruct(FAT_FILE_PTR fat_file){
char temp_buffer[20];
memcpy(temp_buffer, (BYTE*)fat_file->dir_name, 11);
temp_buffer[11] = 0;
printf("dir_name: %s\n", temp_buffer);
printf("dir_attr: %x\n", fat_file->dir_attr);
printf("dir_ntres: %x\n", fat_file->dir_ntres);
printf("dir_crt_time_tenth: %x\n", fat_file->dir_crt_time_tenth);
printf("dir_crt_time: %x\n", fat_file->dir_crt_time);
printf("dir_crt_date: %x\n", fat_file->dir_crt_date);
printf("dir_lst_acc_date: %x\n", fat_file->dir_lst_acc_date);
printf("dir_clust_hi: %x\n", fat_file->dir_clust_hi);
printf("dir_wrt_time: %x\n", fat_file->dir_wrt_time);
printf("dir_wrt_date: %x\n", fat_file->dir_wrt_date);
printf("dir_clust_low: %x\n", fat_file->dir_clust_low);
printf("dir_file_size: %x\n", fat_file->dir_file_size);
}
#endif
#if FAT_DEBUG
void debug_printBpbFat(BPB_FAT_PTR bpb_fat_ptr){
printf("Bpb Fat\n");
printf("bytes_per_sec: %ld\n", bpb_fat_ptr->bytes_per_sec);
printf("sec_per_clust: %ld\n", bpb_fat_ptr->sec_per_clust);
printf("rsvd_sec_cnt: %ld\n", bpb_fat_ptr->rsvd_sec_cnt);
printf("num_fats: %ld\n", bpb_fat_ptr->num_fats);
printf("root_ent_cnt: %ld\n", bpb_fat_ptr->root_ent_cnt);
printf("tot_sec_16: %ld\n", bpb_fat_ptr->tot_sec_16);
//printf("media;
printf("fat_size_16: %ld\n", bpb_fat_ptr->fat_size_16);
// printf("sec_per_trck;
// printf("num_heads;
// printf("hidden_sec;
// printf("tot_sec_32;
}
#endif
/* Cluster type manipulations */
#define DEBUG_DOCLUSTER_OP FALSE
int doClusterOp(FILE_HNDL_PTR fh)
{
LONG sec_num=0;
#if FAT_DEBUG
if (DEBUG_DOCLUSTER_OP){
printf("doClusterOp: OP=");
switch (fh->cluster_op)
{
case CLUSTER_READ:
printf("CLUSTER_READ ");
break;
case CLUSTER_WRITE:
printf("CLUSTER_WRITE ");
break;
case ROOT_READ:
printf("ROOT_READ ");
break;
case ROOT_WRITE:
printf("ROOT_WRITE ");
break;
default:
printf("UNSUPPORTED ");
}
printf("Op1=%ld Op2=%ld\n",fh->cluster_op_data1,fh->cluster_op_data2);
}
#endif
/* sanity checking */
if((fh->cluster_op == CLUSTER_READ) ||
(fh->cluster_op == CLUSTER_WRITE)){
if(fh->cluster_op_data2 > fh->vol_ptr->bpb_fat_ptr->sec_per_clust)
return 1;
}else if((fh->cluster_op == ROOT_READ) ||
(fh->cluster_op == ROOT_WRITE)){
}
/* compute the correct sector */
if((fh->cluster_op == CLUSTER_READ) ||
(fh->cluster_op == CLUSTER_WRITE)){
sec_num = /* fh->vol_ptr->bpb_sector_offset + */
fh->vol_ptr->fat_data_sector + (fh->vol_ptr->bpb_fat_ptr->sec_per_clust * (fh->cluster_op_data1-2));
}else if((fh->cluster_op == ROOT_READ) ||
(fh->cluster_op == ROOT_WRITE)){
sec_num = (fh->vol_ptr->root_sector);
}
sec_num += fh->cluster_op_data2;
#if FAT_DEBUG
if(DEBUG_DOCLUSTER_OP){
printf("Reading cluster: %ld, sector_offset: %ld\n", fh->cluster_op_data1, fh->cluster_op_data2);
printf("Reading sector num: %ld\n", sec_num);
}
#endif
if(fh->cluster_op == CLUSTER_READ){
fatReadLogicalSector(sec_num, 1, fh->fat_file_buf);
}else if(fh->cluster_op == CLUSTER_WRITE){
fatWriteLogicalSector(sec_num, 1, fh->fat_file_buf);
}else if(fh->cluster_op == ROOT_READ){
fatReadLogicalSector(sec_num, 1, fh->fat_file_buf);
}else if(fh->cluster_op == ROOT_WRITE){
fatWriteLogicalSector(sec_num, 1, fh->fat_file_buf);
}else
return 1;
return 0;
}
/*
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -