⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatfs_supp.c

📁 该工程是从ecos嵌入式系统下移植过来的一个小型的fat16文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================////      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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -