?? fatfs_supp.c
字號:
//==========================================================================//// fatfs_supp.c//// FAT file system support functions////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 2003 Savin Zlobec //// eCos 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 2 or (at your option) any later version.//// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): savin // Date: 2003-06-30////####DESCRIPTIONEND####////==========================================================================#include "cyg_type.h"#include "cyg_ass.h"#include "io.h"#include "types.h"#include "fatfs.h"#include "stdio.h"#include "Blockdevice.h"#include "windows.h"//==========================================================================// FAT defines & macros// -------------------------------------------------------------------------// FAT dir entry attributes#define DENTRY_ATTR_RDONLY 0x01 // Read only#define DENTRY_ATTR_HIDDEN 0x02 // Hidden#define DENTRY_ATTR_SYSTEM 0x04 // System#define DENTRY_ATTR_VOLUME 0x08 // Volume label#define DENTRY_ATTR_DIR 0x10 // Subdirectory#define DENTRY_ATTR_ARCHIVE 0x20 // Needs archiving// -------------------------------------------------------------------------// FAT dir entry attributes macros#define DENTRY_IS_RDONLY(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_RDONLY)#define DENTRY_IS_HIDDEN(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_HIDDEN)#define DENTRY_IS_SYSTEM(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_SYSTEM)#define DENTRY_IS_VOLUME(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_VOLUME)#define DENTRY_IS_DIR(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_DIR)#define DENTRY_IS_ARCHIVE(_dentry_) ((_dentry_)->attr & DENTRY_ATTR_ARCHIVE)#define DENTRY_IS_DELETED(_dentry_) \ (0xE5 == (unsigned char)((_dentry_)->name[0]))#define DENTRY_IS_ZERO(_dentry_) \ (0x00 == (unsigned char)((_dentry_)->name[0]))// -------------------------------------------------------------------------// FAT disk data access macros// FIXME: support big endian machines! #define GET_BYTE(_data_, _var_, _off_) \ (_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) )#define GET_WORD(_data_, _var_, _off_) \ (_var_ = *( ((cyg_uint8 *)_data_) + (_off_) ) | \ *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8)#define GET_DWORD(_data_, _var_, _off_) \ (_var_ = *( ((cyg_uint8 *)_data_) + (_off_)) | \ *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) << 8 | \ *( ((cyg_uint8 *)_data_) + (_off_) + 2 ) << 16 | \ *( ((cyg_uint8 *)_data_) + (_off_) + 3 ) << 24)#define GET_BYTES(_data_, _var_, _size_, _off_) \ memcpy((void *)(_var_), (void*)(((cyg_uint8 *)_data_)+(_off_)),_size_)#define SET_BYTE(_data_, _val_, _off_) \ (*( ((cyg_uint8 *)_data_) + (_off_) ) = _val_)#define SET_WORD(_data_, _val_, _off_) \ do { \ *( ((cyg_uint8 *)_data_) + (_off_) ) = _val_ & 0xFF; \ *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8) & 0xFF; \ } while (0)#define SET_DWORD(_data_, _val_, _off_) \ do { \ *( ((cyg_uint8 *)_data_) + (_off_) ) = _val_ & 0xFF; \ *( ((cyg_uint8 *)_data_) + (_off_) + 1 ) = (_val_ >> 8) & 0xFF; \ *( ((cyg_uint8 *)_data_) + (_off_) + 2 ) = (_val_ >> 16) & 0xFF; \ *( ((cyg_uint8 *)_data_) + (_off_) + 3 ) = (_val_ >> 24) & 0xFF; \ } while (0)#define SET_BYTES(_data_, _var_, _size_, _off_) \ memcpy((void *)(((cyg_uint8 *)_data_)+(_off_)), (void *)(_var_), _size_)// -------------------------------------------------------------------------// FAT table entries types #define TENTRY_REGULAR 0 // Used when entry points to next file cluster #define TENTRY_FREE 1 // Free cluster#define TENTRY_LAST 2 // Last cluster of file #define TENTRY_RESERVED 3 // Reserved cluster#define TENTRY_BAD 4 // Bad cluster // -------------------------------------------------------------------------// FAT table structures size #define DENTRY_SIZE 0x20 // Dir entry size// -------------------------------------------------------------------------// Time & date defines #define JD_1_JAN_1970 2440588 // 1 Jan 1970 in Julian day number// -------------------------------------------------------------------------// Code tracing defines #ifdef FATFS_TRACE_FAT_TABLE# define TFT 1#else# define TFT 0#endif#ifdef FATFS_TRACE_DIR_ENTRY# define TDE 1#else# define TDE 0#endif#ifdef FATFS_TRACE_CLUSTER# define TCL 1#else# define TCL 0#endif#ifdef FATFS_TRACE_DATA# define TDO 1#else# define TDO 0#endif // -------------------------------------------------------------------------// FAT table entry type strings #if TFTstatic const char *tentry_type_name[5] = { "REGULAR", "FREE", "LAST", "RESERVED", "BAD"}; #endif//==========================================================================// FAT structures // -------------------------------------------------------------------------// FAT table boot record structure typedef struct fat_boot_record_s{ cyg_uint16 jump; // 00h : Jump code// cyg_uint8 jump0; // + NOP char oem_name[8+1]; // 03h : OEM name cyg_uint16 bytes_per_sec; // 0Bh : cyg_bytes per sector cyg_uint8 sec_per_clust; // 0Dh : Sectors per cluster cyg_uint16 res_sec_num; // 0Eh : Number of reserved sectors cyg_uint8 fat_tbls_num; // 10h : Number of copies of fat cyg_uint16 max_root_dents; // 11h : Maximum number of root dir entries cyg_uint16 sec_num_32; // 13h : Number of sectors in partition < 32MB cyg_uint8 media_desc; // 15h : Media descriptor cyg_uint16 sec_per_fat; // 16h : Sectors per FAT cyg_uint16 sec_per_track; // 18h : Sectors per track cyg_uint16 heads_num; // 1Ah : Number of heads cyg_uint32 hsec_num; // 1Ch : Number of hidden sectors cyg_uint32 sec_num; // 20h : Number of sectors in partition cyg_uint16 ldrv_num; // 24h : Logical drive number of partition cyg_uint8 ext_sig; // 26h : Extended signature cyg_uint32 ser_num; // 27h : Serial number of partition char vol_name[11+1]; // 2Bh : Volume name of partition char fat_name[8+1]; // 36h : FAT name// unsigned char exe_code[448]; // 3Eh : Executable code unsigned char exe_marker[2]; // 1FEh: Executable marker (55h AAh)} fat_boot_record_t;// -------------------------------------------------------------------------// FAT dir entry structure typedef struct fat_dir_entry_s{ char name[8+1]; // 00h : Name char ext[3+1]; // 08h : Extension cyg_uint8 attr; // 0Bh : Attribute cyg_uint8 nt_reserved; // 0Ch : Win NT Reserved field cyg_uint8 crt_sec_100; // 0Dh : Creation time ms stamp 0 - 199 cyg_uint16 crt_time; // 0Eh : Creation time cyg_uint16 crt_date; // 10h : Creation date cyg_uint16 acc_date; // 12h : Last access date cyg_uint16 cluster_HI; // 14h : Starting cluster HI WORD (FAT32) cyg_uint16 wrt_time; // 16h : Time cyg_uint16 wrt_date; // 18h : Date cyg_uint16 cluster; // 1Ah : Starting cluster cyg_uint32 size; // 1Ch : Size of the file fatfs_data_pos_t pos; // Positon on disk} fat_dir_entry_t;// -------------------------------------------------------------------------// FAT cluster opts typedef enum cluster_opts_e{ CO_NONE = 0x00, // NULL option CO_EXTEND = 0x01, // Extend cluster chain if one cluster too short CO_ERASE_NEW = 0x02, // Erase newly allocated cluster CO_MARK_LAST = 0x04 // Mark newly allocated cluster as last} cluster_opts_t;//==========================================================================// Utility functions // -------------------------------------------------------------------------// get_val_log2()// Gets the log2 of given value or returns 0 if value is // not power of 2. static cyg_uint32 get_val_log2(cyg_uint32 val){ cyg_uint32 i, log2; i = val; log2 = 0; while (0 == (i & 1)) { i >>= 1; log2++; } if (i != 1) return 0; else return log2;}// -------------------------------------------------------------------------// get_data_disk_apos()// Gets the absolute data position on disk from cluster number and// position inside given cluster. static cyg_uint32get_data_disk_apos(fatfs_disk_t *disk, cyg_uint32 cluster, cyg_uint32 pos){ return (disk->fat_data_pos + disk->cluster_size * (cluster - 2) + pos);}// -------------------------------------------------------------------------// jdays_to_gdate()// Converts juilan days into gregorian date. static voidjdays_to_gdate(cyg_uint32 jd, int *day, int *month, int *year){ cyg_uint32 l, n, i, j; l = jd + 68569; n = (4 * l) / 146097; l = l - (146097 * n + 3) / 4; i = (4000 * (l + 1)) / 1461001; l = l - (1461 * i) / 4 + 31; j = (80 * l) / 2447; *day = l - (2447 * j) / 80; l = j / 11; *month = j + 2 - (12 * l); *year = 100 * (n - 49) + i + l;}// -------------------------------------------------------------------------// gdate_to_jdays()// Converts gregorian date to juilan days. static voidgdate_to_jdays(int day, int month, int year, cyg_uint32 *jd){ *jd = day - 32075 + 1461*(year + 4800 + (month - 14)/12)/4 + 367*(month - 2 - (month - 14)/12*12)/12 - 3*((year + 4900 + (month - 14)/12)/100)/4;} // -------------------------------------------------------------------------// date_unix2dos()// Converts unix timestamp to dos time and date. static voiddate_unix2dos(cyg_uint32 unix_timestamp, cyg_uint16 *dos_time, cyg_uint16 *dos_date){ cyg_uint32 jd; cyg_uint16 dtime, ddate; int hour, min, sec; int day, month, year; hour = (unix_timestamp / 3600) % 24; min = (unix_timestamp / 60) % 60; sec = unix_timestamp % 60; jd = JD_1_JAN_1970 + unix_timestamp / (3600 * 24); jdays_to_gdate(jd, &day, &month, &year); printf( "ts=%d date=%d:%d:%d %d-%d-%d", unix_timestamp, hour, min, sec, year, month, day); if (year < 1980) year = 1980; dtime = (hour << 11) | (min << 5) | (sec >> 1); ddate = ((year - 1980) << 9) | (month << 5) | day; printf( "dos time=%d date=%d", dtime, ddate); if (NULL != dos_time) *dos_time = dtime; if (NULL != dos_date) *dos_date = ddate;}// -------------------------------------------------------------------------// date_dos2unix()// Converts dos time and date to unix timestamp. static voiddate_dos2unix(cyg_uint16 dos_time, cyg_uint16 dos_date, cyg_uint32 *unix_timestamp){ int hour, min, sec; int day, month, year; cyg_uint32 ts; sec = (dos_time & ((1<<5)-1)) * 2; dos_time >>= 5; min = (dos_time & ((1<<6)-1)); dos_time >>= 6; hour = dos_time; day = (dos_date & ((1<<5)-1)); dos_date >>= 5; month = (dos_date & ((1<<4)-1)); dos_date >>= 4; year = dos_date + 1980; gdate_to_jdays(day, month, year, &ts); ts -= JD_1_JAN_1970; ts = (ts * 24 * 3600) + (sec + min * 60 + hour * 3600); *unix_timestamp = ts; printf( "dos time=%d date=%d", dos_time, dos_date); printf( "timestamp=%d date=%d:%d:%d %d-%d-%d", ts, hour, min, sec, year, month, day);}//==========================================================================// FAT boot record functions // -------------------------------------------------------------------------// print_boot_record()// Prints FAT boot record.#if TFT static voidprint_boot_record(fat_boot_record_t* fbr){ diag_printf("FAT: FBR jump code: 0x%02X\n", fbr->jump); diag_printf("FAT: FBR oem name: '%.8s'\n", fbr->oem_name); diag_printf("FAT: FBR bytes per sec: %u\n", fbr->bytes_per_sec); diag_printf("FAT: FBR sec per cluster: %u\n", fbr->sec_per_clust); diag_printf("FAT: FBR reserved sec: %u\n", fbr->res_sec_num); diag_printf("FAT: FBR fat tbls num: %u\n", fbr->fat_tbls_num); diag_printf("FAT: FBR max root dents: %u\n", fbr->max_root_dents); diag_printf("FAT: FBR sec num (32): %u\n", fbr->sec_num_32); diag_printf("FAT: FBR media desc: 0x%02X\n", fbr->media_desc); diag_printf("FAT: FBR sec per fat: %u\n", fbr->sec_per_fat); diag_printf("FAT: FBR sec per track: %u\n", fbr->sec_per_track); diag_printf("FAT: FBR heads num: %u\n", fbr->heads_num); diag_printf("FAT: FBR hidden sec num: %u\n", fbr->hsec_num); diag_printf("FAT: FBR sec num: %u\n", fbr->sec_num); diag_printf("FAT: FBR log drv num: %u\n", fbr->ldrv_num); diag_printf("FAT: FBR ext sig: 0x%02X\n", fbr->ext_sig); diag_printf("FAT: FBR ser num: 0x%08X\n", fbr->ser_num); diag_printf("FAT: FBR vol name: '%.11s'\n", fbr->vol_name); diag_printf("FAT: FBR fat name: '%.8s'\n", fbr->fat_name); diag_printf("FAT: FBR exe mark: 0x%02X 0x%02X\n", fbr->exe_marker[0], fbr->exe_marker[1]);}#endif // TFT// -------------------------------------------------------------------------// read_boot_record()// Reads FAT boot record from disk. static int read_boot_record(fatfs_disk_t *disk, fat_boot_record_t *fbr){ int len, err; unsigned char data[0x3E]; len = 0x3E; err = ReadBlock((void*)data, &len, 0, 0); if (err != ENOERR) return err; GET_WORD(data, fbr->jump, 0x00); GET_BYTES(data, fbr->oem_name, 8, 0x03); GET_WORD(data, fbr->bytes_per_sec, 0x0B); GET_BYTE(data, fbr->sec_per_clust, 0x0D); GET_WORD(data, fbr->res_sec_num, 0x0E); GET_BYTE(data, fbr->fat_tbls_num, 0x10);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -