Ticket #720: msdos_format.diff

File msdos_format.diff, 53.0 KB (added by thomas.doerfler, on Dec 3, 2006 at 1:31:12 PM)

msdos_format.diff

  • cpukit/libfs/src/dosfs/dosfs.h

    diff -Nur rtems-4.6.2/cpukit/libfs/src/dosfs/dosfs.h rtems-4.6.2-bigimfs-ackhack/cpukit/libfs/src/dosfs/dosfs.h
    old new  
    2424
    2525extern rtems_filesystem_operations_table  msdos_ops;
    2626
     27#define MSDOS_FMT_FATANY 0
     28#define MSDOS_FMT_FAT12  1
     29#define MSDOS_FMT_FAT16  2
     30#define MSDOS_FMT_FAT32  3
     31/*
     32 * data to be filled out for formatter: parameters for format call
     33 * any parameter set to 0 or NULL will be automatically detected/computed
     34 */
     35typedef struct {
     36  const char *OEMName;            /* OEM Name string or NULL               */
     37  const char *VolLabel;           /* Volume Label string or NULL           */
     38  unsigned32 sectors_per_cluster; /* request value: sectors per cluster    */
     39  unsigned32 fat_num;             /* request value: number of FATs on disk */
     40  unsigned32 files_per_root_dir;  /* request value: file entries in root   */
     41  unsigned8 fattype;              /* request value: MSDOS_FMT_FAT12/16/32  */
     42  unsigned8 media;                /* media code. default: 0xF8             */
     43  boolean   quick_format;         /* TRUE: do not clear out data sectors   */
     44  unsigned32 cluster_align;       /* requested value: cluster alignment    */
     45                                  /*   make sector number of first sector  */
     46                                  /*   of first cluster divisible by this  */
     47                                  /*   value. This can optimize clusters   */
     48                                  /*   to be located at start of track     */
     49                                  /*   or start of flash block             */
     50} msdos_format_request_param_t;
     51
     52/*=========================================================================*\
     53| Function:                                                                 |
     54\*-------------------------------------------------------------------------*/
     55int msdos_format
     56(
     57/*-------------------------------------------------------------------------*\
     58| Purpose:                                                                  |
     59|     format device with msdos filesystem                                   |
     60+---------------------------------------------------------------------------+
     61| Input Parameters:                                                         |
     62\*-------------------------------------------------------------------------*/
     63 const char *devname,                        /* device name                */
     64 const msdos_format_request_param_t *rqdata  /* requested fmt parameters   */
     65                                             /* set to NULL for automatic  */
     66                                             /* determination              */
     67 );
     68/*-------------------------------------------------------------------------*\
     69| Return Value:                                                             |
     70|    0, if success, -1 and errno if failed                                  |
     71\*=========================================================================*/
     72
    2773#ifdef __cplusplus
    2874}
    2975#endif
  • cpukit/libfs/src/dosfs/fat.c

    diff -Nur rtems-4.6.2/cpukit/libfs/src/dosfs/fat.c rtems-4.6.2-bigimfs-ackhack/cpukit/libfs/src/dosfs/fat.c
    old new  
    247247    }
    248248    close(fd);
    249249
    250     vol->bps = FAT_BR_BYTES_PER_SECTOR(boot_rec);
     250    vol->bps = FAT_GET_BR_BYTES_PER_SECTOR(boot_rec);
    251251 
    252252    if ( (vol->bps != 512)  &&
    253253         (vol->bps != 1024) &&
     
    263263    for (vol->sec_log2 = 0, i = vol->bps; (i & 1) == 0;
    264264         i >>= 1, vol->sec_log2++);
    265265
    266     vol->spc = FAT_BR_SECTORS_PER_CLUSTER(boot_rec);
     266    vol->spc = FAT_GET_BR_SECTORS_PER_CLUSTER(boot_rec);
    267267    /*
    268268     * "sectors per cluster" of zero is invalid
    269269     * (and would hang the following loop)
     
    289289    for (vol->bpc_log2 = 0, i = vol->bpc; (i & 1) == 0;
    290290         i >>= 1, vol->bpc_log2++);
    291291
    292     vol->fats = FAT_BR_FAT_NUM(boot_rec);
    293     vol->fat_loc = FAT_BR_RESERVED_SECTORS_NUM(boot_rec);
     292    vol->fats = FAT_GET_BR_FAT_NUM(boot_rec);
     293    vol->fat_loc = FAT_GET_BR_RESERVED_SECTORS_NUM(boot_rec);
    294294
    295     vol->rdir_entrs = FAT_BR_FILES_PER_ROOT_DIR(boot_rec);
     295    vol->rdir_entrs = FAT_GET_BR_FILES_PER_ROOT_DIR(boot_rec);
    296296   
    297297    /* calculate the count of sectors occupied by the root directory */
    298298    vol->rdir_secs = ((vol->rdir_entrs * FAT_DIRENTRY_SIZE) + (vol->bps - 1)) /
     
    300300
    301301    vol->rdir_size = vol->rdir_secs << vol->sec_log2;
    302302
    303     if ( (FAT_BR_SECTORS_PER_FAT(boot_rec)) != 0)
    304         vol->fat_length = FAT_BR_SECTORS_PER_FAT(boot_rec);
     303    if ( (FAT_GET_BR_SECTORS_PER_FAT(boot_rec)) != 0)
     304        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT(boot_rec);
    305305    else
    306         vol->fat_length = FAT_BR_SECTORS_PER_FAT32(boot_rec);
     306        vol->fat_length = FAT_GET_BR_SECTORS_PER_FAT32(boot_rec);
    307307 
    308308    vol->data_fsec = vol->fat_loc + vol->fats * vol->fat_length +
    309309                     vol->rdir_secs;
     
    311311    /* for  FAT12/16 root dir starts at(sector) */
    312312    vol->rdir_loc = vol->fat_loc + vol->fats * vol->fat_length;
    313313 
    314     if ( (FAT_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
    315         vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM16(boot_rec);
     314    if ( (FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec)) != 0)
     315        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM16(boot_rec);
    316316    else
    317         vol->tot_secs = FAT_BR_TOTAL_SECTORS_NUM32(boot_rec);
     317        vol->tot_secs = FAT_GET_BR_TOTAL_SECTORS_NUM32(boot_rec);
    318318 
    319319    data_secs = vol->tot_secs - vol->data_fsec;
    320320 
     
    345345 
    346346    if (vol->type == FAT_FAT32)
    347347    {
    348         vol->rdir_cl = FAT_BR_FAT32_ROOT_CLUSTER(boot_rec);
     348        vol->rdir_cl = FAT_GET_BR_FAT32_ROOT_CLUSTER(boot_rec);
    349349     
    350         vol->mirror = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
     350        vol->mirror = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_MIRROR;
    351351        if (vol->mirror)
    352             vol->afat = FAT_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
     352            vol->afat = FAT_GET_BR_EXT_FLAGS(boot_rec) & FAT_BR_EXT_FLAGS_FAT_NUM;
    353353        else
    354354            vol->afat = 0;
    355355
    356         vol->info_sec = FAT_BR_FAT32_FS_INFO_SECTOR(boot_rec);
     356        vol->info_sec = FAT_GET_BR_FAT32_FS_INFO_SECTOR(boot_rec);
    357357        if( vol->info_sec == 0 )
    358358        {
    359359            rtems_disk_release(vol->dd);
     
    369369                return -1;
    370370            }   
    371371     
    372             if (FAT_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
     372            if (FAT_GET_FSINFO_LEAD_SIGNATURE(fs_info_sector) !=
    373373                FAT_FSINFO_LEAD_SIGNATURE_VALUE)
    374374            {   
    375375                rtems_disk_release(vol->dd);
     
    385385                    return -1;
    386386                }   
    387387                   
    388                 vol->free_cls = FAT_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
    389                 vol->next_cl = FAT_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
     388                vol->free_cls = FAT_GET_FSINFO_FREE_CLUSTER_COUNT(fs_info_sector);
     389                vol->next_cl = FAT_GET_FSINFO_NEXT_FREE_CLUSTER(fs_info_sector);
    390390                rc = fat_fat32_update_fsinfo_sector(mt_entry, 0xFFFFFFFF,
    391391                                                    0xFFFFFFFF);
    392392                if ( rc != RC_OK )
  • cpukit/libfs/src/dosfs/fat.h

    diff -Nur rtems-4.6.2/cpukit/libfs/src/dosfs/fat.h rtems-4.6.2-bigimfs-ackhack/cpukit/libfs/src/dosfs/fat.h
    old new  
    5151 */
    5252
    5353#if (CPU_BIG_ENDIAN == TRUE)
    54 #    define CF_LE_W(v) CPU_swap_u16((unsigned16)v)
    55 #    define CF_LE_L(v) CPU_swap_u32((unsigned32)v)
    56 #    define CT_LE_W(v) CPU_swap_u16((unsigned16)v)
    57 #    define CT_LE_L(v) CPU_swap_u32((unsigned32)v)
     54#    define CF_LE_W(v) CPU_swap_u16((unsigned16)(v))
     55#    define CF_LE_L(v) CPU_swap_u32((unsigned32)(v))
     56#    define CT_LE_W(v) CPU_swap_u16((unsigned16)(v))
     57#    define CT_LE_L(v) CPU_swap_u32((unsigned32)(v))
    5858#else 
    5959#    define CF_LE_W(v) (v)
    6060#    define CF_LE_L(v) (v)
     
    101101#define FAT_FAT32_MASK         (unsigned32)0x0FFFFFFF
    102102
    103103#define FAT_MAX_BPB_SIZE       90
     104#define FAT_TOTAL_MBR_SIZE    512
    104105
    105106/* size of useful information in FSInfo sector */
    106107#define FAT_USEFUL_INFO_SIZE   12
    107108
    108 #define FAT_VAL8(x, ofs)       (unsigned8)(*((unsigned8 *)(x) + (ofs)))
    109  
    110 #define FAT_VAL16(x, ofs)                                   \
     109#define FAT_GET_ADDR(x, ofs)       ((unsigned8 *)(x) + (ofs))
     110
     111#define FAT_GET_VAL8(x, ofs)       (unsigned8)(*((unsigned8 *)(x) + (ofs)))
     112
     113#define FAT_GET_VAL16(x, ofs)                               \
    111114    (unsigned16)( (*((unsigned8 *)(x) + (ofs))) |           \
    112115                  ((*((unsigned8 *)(x) + (ofs) + 1)) << 8) )
    113116
    114 #define FAT_VAL32(x, ofs)                                                 \
     117#define FAT_GET_VAL32(x, ofs)                                             \
    115118    (unsigned32)( (unsigned32)(*((unsigned8 *)(x) + (ofs))) |             \
    116119                  ((unsigned32)(*((unsigned8 *)(x) + (ofs) + 1)) << 8)  | \
    117120                  ((unsigned32)(*((unsigned8 *)(x) + (ofs) + 2)) << 16) | \
    118121                  ((unsigned32)(*((unsigned8 *)(x) + (ofs) + 3)) << 24) )
    119122                   
     123#define FAT_SET_VAL8(x, ofs,val)                    \
     124                 (*((unsigned8 *)(x)+(ofs))=(unsigned8)(val))
     125 
     126#define FAT_SET_VAL16(x, ofs,val) do {              \
     127                 FAT_SET_VAL8((x),(ofs),(val));     \
     128                 FAT_SET_VAL8((x),(ofs)+1,(val)>>8);\
     129                 } while (0)
     130
     131#define FAT_SET_VAL32(x, ofs,val) do {               \
     132                 FAT_SET_VAL16((x),(ofs),(val));     \
     133                 FAT_SET_VAL16((x),(ofs)+2,(val)>>16);\
     134                 } while (0)
     135
    120136/* macros to access boot sector fields */
    121 #define FAT_BR_BYTES_PER_SECTOR(x)       FAT_VAL16(x, 11)
    122 #define FAT_BR_SECTORS_PER_CLUSTER(x)    FAT_VAL8(x, 13)
    123 #define FAT_BR_RESERVED_SECTORS_NUM(x)   FAT_VAL16(x, 14)
    124 #define FAT_BR_FAT_NUM(x)                FAT_VAL8(x, 16)
    125 #define FAT_BR_FILES_PER_ROOT_DIR(x)     FAT_VAL16(x, 17)
    126 #define FAT_BR_TOTAL_SECTORS_NUM16(x)    FAT_VAL16(x, 19)
    127 #define FAT_BR_MEDIA(x)                  FAT_VAL8(x, 21)
    128 #define FAT_BR_SECTORS_PER_FAT(x)        FAT_VAL16(x, 22)
    129 #define FAT_BR_TOTAL_SECTORS_NUM32(x)    FAT_VAL32(x, 32)
    130 #define FAT_BR_SECTORS_PER_FAT32(x)      FAT_VAL32(x, 36)
    131 #define FAT_BR_EXT_FLAGS(x)              FAT_VAL16(x, 40)
    132 #define FAT_BR_FAT32_ROOT_CLUSTER(x)     FAT_VAL32(x, 44)
    133 #define FAT_BR_FAT32_FS_INFO_SECTOR(x)   FAT_VAL16(x, 48)
    134 #define FAT_FSINFO_LEAD_SIGNATURE(x)     FAT_VAL32(x, 0)
     137#define FAT_GET_BR_JMPBOOT(x)                FAT_GET_VAL8( x,  0)
     138#define FAT_SET_BR_JMPBOOT(x,val)            FAT_SET_VAL8( x,  0,val)
     139
     140#define FAT_GET_ADDR_BR_OEMNAME(x)           FAT_GET_ADDR( x,  3)
     141#define FAT_BR_OEMNAME_SIZE              (8)
     142
     143#define FAT_GET_BR_BYTES_PER_SECTOR(x)       FAT_GET_VAL16(x, 11)
     144#define FAT_SET_BR_BYTES_PER_SECTOR(x,val)   FAT_SET_VAL16(x, 11,val)
     145
     146#define FAT_GET_BR_SECTORS_PER_CLUSTER(x)    FAT_GET_VAL8( x, 13)
     147#define FAT_SET_BR_SECTORS_PER_CLUSTER(x,val)FAT_SET_VAL8( x, 13,val)
     148
     149#define FAT_GET_BR_RESERVED_SECTORS_NUM(x)   FAT_GET_VAL16(x, 14)
     150#define FAT_SET_BR_RESERVED_SECTORS_NUM(x,val) FAT_SET_VAL16(x, 14,val)
     151
     152#define FAT_GET_BR_FAT_NUM(x)                FAT_GET_VAL8( x, 16)
     153#define FAT_SET_BR_FAT_NUM(x,val)            FAT_SET_VAL8( x, 16,val)
     154
     155#define FAT_GET_BR_FILES_PER_ROOT_DIR(x)     FAT_GET_VAL16(x, 17)
     156#define FAT_SET_BR_FILES_PER_ROOT_DIR(x,val) FAT_SET_VAL16(x, 17,val)
     157
     158#define FAT_GET_BR_TOTAL_SECTORS_NUM16(x)    FAT_GET_VAL16(x, 19)
     159#define FAT_SET_BR_TOTAL_SECTORS_NUM16(x,val)FAT_SET_VAL16(x, 19,val)
     160
     161#define FAT_GET_BR_MEDIA(x)                  FAT_GET_VAL8( x, 21)
     162#define FAT_SET_BR_MEDIA(x,val)              FAT_SET_VAL8( x, 21,val)
     163
     164#define FAT_GET_BR_SECTORS_PER_FAT(x)        FAT_GET_VAL16(x, 22)
     165#define FAT_SET_BR_SECTORS_PER_FAT(x,val)    FAT_SET_VAL16(x, 22,val)
     166
     167#define FAT_GET_BR_SECTORS_PER_TRACK(x)      FAT_GET_VAL16(x, 24)
     168#define FAT_SET_BR_SECTORS_PER_TRACK(x,val)  FAT_SET_VAL16(x, 24,val)
     169
     170#define FAT_GET_BR_NUMBER_OF_HEADS(x)        FAT_GET_VAL16(x, 26)
     171#define FAT_SET_BR_NUMBER_OF_HEADS(x,val)    FAT_SET_VAL16(x, 26,val)
     172
     173#define FAT_GET_BR_HIDDEN_SECTORS(x)         FAT_GET_VAL32(x, 28)
     174#define FAT_SET_BR_HIDDEN_SECTORS(x,val)     FAT_SET_VAL32(x, 28,val)
     175
     176#define FAT_GET_BR_TOTAL_SECTORS_NUM32(x)    FAT_GET_VAL32(x, 32)
     177#define FAT_SET_BR_TOTAL_SECTORS_NUM32(x,val) FAT_SET_VAL32(x, 32,val)
     178  /* --- start of FAT12/16 specific fields */
     179#define FAT_GET_BR_DRVNUM(x)                 FAT_GET_VAL8( x, 36)
     180#define FAT_SET_BR_DRVNUM(x,val)             FAT_SET_VAL8( x, 36,val)
     181
     182#define FAT_GET_BR_RSVD1(x)                  FAT_GET_VAL8( x, 37)
     183#define FAT_SET_BR_RSVD1(x,val)              FAT_SET_VAL8( x, 37,val)
     184
     185#define FAT_GET_BR_BOOTSIG(x)                FAT_GET_VAL8( x, 38)
     186#define FAT_SET_BR_BOOTSIG(x,val)            FAT_SET_VAL8( x, 38,val)
     187#define FAT_BR_BOOTSIG_VAL               (0x29)
     188
     189#define FAT_GET_BR_VOLID(x)                  FAT_GET_VAL32(x, 39)
     190#define FAT_SET_BR_VOLID(x,val)              FAT_SET_VAL32(x, 39,val)
     191
     192#define FAT_GET_ADDR_BR_VOLLAB(x)            FAT_GET_ADDR (x, 43)
     193#define FAT_BR_VOLLAB_SIZE               (11)
     194
     195#define FAT_GET_ADDR_BR_FILSYSTYPE(x)        FAT_GET_ADDR (x, 54)
     196#define FAT_BR_FILSYSTYPE_SIZE           (8)
     197  /* --- end of FAT12/16 specific fields */
     198  /* --- start of FAT32 specific fields */
     199#define FAT_GET_BR_SECTORS_PER_FAT32(x)      FAT_GET_VAL32(x, 36)
     200#define FAT_SET_BR_SECTORS_PER_FAT32(x,val)  FAT_SET_VAL32(x, 36,val)
     201
     202#define FAT_GET_BR_EXT_FLAGS(x)              FAT_GET_VAL16(x, 40)
     203#define FAT_SET_BR_EXT_FLAGS(x,val)          FAT_SET_VAL16(x, 40,val)
     204
     205#define FAT_GET_BR_FSVER(x)                  FAT_GET_VAL16(x, 42)
     206#define FAT_SET_BR_FSVER(x,val)              FAT_SET_VAL16(x, 42,val)
     207
     208#define FAT_GET_BR_FAT32_ROOT_CLUSTER(x)     FAT_GET_VAL32(x, 44)
     209#define FAT_SET_BR_FAT32_ROOT_CLUSTER(x,val) FAT_SET_VAL32(x, 44,val)
     210
     211#define FAT_GET_BR_FAT32_FS_INFO_SECTOR(x)   FAT_GET_VAL16(x, 48)
     212#define FAT_SET_BR_FAT32_FS_INFO_SECTOR(x,val) FAT_SET_VAL16(x, 48,val)
     213
     214#define FAT_GET_BR_FAT32_BK_BOOT_SECTOR(x)   FAT_GET_VAL16(x, 50)
     215#define FAT_SET_BR_FAT32_BK_BOOT_SECTOR(x,val)  FAT_SET_VAL16(x, 50,val)
     216
     217#define FAT_GET_ADDR_BR_FAT32_RESERVED(x)    FAT_GET_ADDR (x, 52)
     218#define FAT_BR_FAT32_RESERVED_SIZE       (12)
     219
     220#define FAT_GET_BR_FAT32_DRVNUM(x)           FAT_GET_VAL8( x, 64)
     221#define FAT_SET_BR_FAT32_DRVNUM(x,val)       FAT_SET_VAL8( x, 64,val)
     222
     223#define FAT_GET_BR_FAT32_RSVD1(x)            FAT_GET_VAL8( x, 65)
     224#define FAT_SET_BR_FAT32_RSVD1(x,val)        FAT_SET_VAL8( x, 65,val)
     225
     226#define FAT_GET_BR_FAT32_BOOTSIG(x)          FAT_GET_VAL8( x, 66)
     227#define FAT_SET_BR_FAT32_BOOTSIG(x,val)      FAT_SET_VAL8( x, 66,val)
     228#define FAT_BR_FAT32_BOOTSIG_VAL         (0x29)
     229
     230#define FAT_GET_BR_FAT32_VOLID(x)            FAT_GET_VAL32(x, 67)
     231#define FAT_SET_BR_FAT32_VOLID(x,val)        FAT_SET_VAL32(x, 67,val)
     232
     233#define FAT_GET_ADDR_BR_FAT32_VOLLAB(x)      FAT_GET_ADDR (x, 71)
     234#define FAT_BR_FAT32_VOLLAB_SIZE         (11)
     235
     236#define FAT_GET_ADDR_BR_FAT32_FILSYSTYPE(x)  FAT_GET_ADDR (x, 82)
     237#define FAT_BR_FAT32_FILSYSTYPE_SIZE     (8)
     238  /* --- end of FAT32 specific fields */
     239
     240#define FAT_GET_BR_SIGNATURE(x)              FAT_GET_VAL16(x,510)
     241#define FAT_SET_BR_SIGNATURE(x,val)          FAT_SET_VAL16(x,510,val)
     242#define FAT_BR_SIGNATURE_VAL                (0xAA55)
     243
     244  /*
     245   * FAT32 FSINFO description
     246   */
     247#define FAT_GET_FSINFO_LEAD_SIGNATURE(x)      FAT_GET_VAL32(x,  0)
     248#define FAT_SET_FSINFO_LEAD_SIGNATURE(x,val)  FAT_SET_VAL32(x,  0,val)
     249#define FAT_FSINFO_LEAD_SIGNATURE_VALUE   (0x41615252)
     250
     251#define FAT_GET_FSINFO_STRUC_SIGNATURE(x)     FAT_GET_VAL32(x,484)
     252#define FAT_SET_FSINFO_STRUC_SIGNATURE(x,val) FAT_SET_VAL32(x,484,val)
     253#define FAT_FSINFO_STRUC_SIGNATURE_VALUE  (0x61417272)
     254
     255#define FAT_GET_FSINFO_TRAIL_SIGNATURE(x)     FAT_GET_VAL32(x,508)
     256#define FAT_SET_FSINFO_TRAIL_SIGNATURE(x,val) FAT_SET_VAL32(x,508,val)
     257#define FAT_FSINFO_TRAIL_SIGNATURE_VALUE  (0x000055AA)
    135258/*
    136259 * I read FSInfo sector from offset 484 to access the information, so offsets
    137260 * of these fields a relative
    138261 */
    139 #define FAT_FSINFO_FREE_CLUSTER_COUNT(x) FAT_VAL32(x, 4)
    140 #define FAT_FSINFO_NEXT_FREE_CLUSTER(x)  FAT_VAL32(x, 8)
     262#define FAT_GET_FSINFO_FREE_CLUSTER_COUNT(x)      FAT_GET_VAL32(x, 4)
     263#define FAT_SET_FSINFO_FREE_CLUSTER_COUNT(x,val)  FAT_SET_VAL32(x, 4,val)
     264#define FAT_GET_FSINFO_NEXT_FREE_CLUSTER(x)       FAT_GET_VAL32(x, 8)
     265#define FAT_SET_FSINFO_NEXT_FREE_CLUSTER(x,val)   FAT_SET_VAL32(x, 8,val)
    141266
    142 #define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET 488
     267#define FAT_FSI_INFO                         484
     268#define FAT_FSINFO_STRUCT_OFFSET             488
     269#define FAT_FSINFO_FREE_CLUSTER_COUNT_OFFSET (FAT_FSINFO_STRUCT_OFFSET+0)
    143270
    144 #define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET  492
     271#define FAT_FSINFO_NEXT_FREE_CLUSTER_OFFSET  (FAT_FSINFO_STRUCT_OFFSET+4)
    145272
    146273#define FAT_RSRVD_CLN                        0x02 
    147274
    148 #define FAT_FSINFO_LEAD_SIGNATURE_VALUE      0x41615252
    149 
    150275#define FAT_FSI_LEADSIG_SIZE                 0x04
    151276
    152 #define FAT_FSI_INFO                         484
     277#define FAT_TOTAL_FSINFO_SIZE               512
    153278
    154279#define MS_BYTES_PER_CLUSTER_LIMIT           0x8000     /* 32K */
    155280
     
    157282
    158283#define FAT_BR_EXT_FLAGS_FAT_NUM             0x000F
    159284
     285#define FAT_BR_MEDIA_FIXED                  0xf8
    160286
    161287#define FAT_DIRENTRY_SIZE          32
    162288 
  • cpukit/libfs/src/dosfs/Makefile.am

    diff -Nur rtems-4.6.2/cpukit/libfs/src/dosfs/Makefile.am rtems-4.6.2-bigimfs-ackhack/cpukit/libfs/src/dosfs/Makefile.am
    old new  
    1515                msdos_free.c msdos_fsunmount.c msdos_handlers_dir.c  \
    1616                msdos_handlers_file.c msdos_init.c msdos_initsupp.c  \
    1717                msdos_misc.c msdos_mknod.c msdos_node_type.c \
    18                 msdos_conv.c
     18                msdos_conv.c msdos_format.c
    1919
    2020if !UNIX
    2121LIB = ${ARCH}/libdosfs.a
  • cpukit/libfs/src/dosfs/msdos_format.c

    diff -Nur rtems-4.6.2/cpukit/libfs/src/dosfs/msdos_format.c rtems-4.6.2-bigimfs-ackhack/cpukit/libfs/src/dosfs/msdos_format.c
    old new  
     1/*===============================================================*\
     2| Project: RTEMS msdos format functionality                       |
     3+-----------------------------------------------------------------+
     4| File: msdos_format.c                                            |
     5+-----------------------------------------------------------------+
     6|                    Copyright (c) 2004 IMD                       |
     7|      Ingenieurbuero fuer Microcomputertechnik Th. Doerfler      |
     8|               <Thomas.Doerfler@imd-systems.de>                  |
     9|                       all rights reserved                       |
     10+-----------------------------------------------------------------+
     11| this file contains msdos_format function. This function         |
     12| formats a disk partition conforming to MS-DOS conventions       |
     13|                                                                 |
     14|  The license and distribution terms for this file may be        |
     15|  found in the file LICENSE in this distribution or at           |
     16|  http://www.rtems.com/license/LICENSE.                          |
     17|                                                                 |
     18+-----------------------------------------------------------------+
     19|   date                      history                        ID   |
     20| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
     21| 29.10.04  creation                                         doe  |
     22\*===============================================================*/
     23
     24#if HAVE_CONFIG_H
     25#include "config.h"
     26#endif
     27
     28#include <sys/types.h>
     29#include <sys/stat.h>
     30#include <fcntl.h>
     31#include <unistd.h>
     32#include <errno.h>
     33#include <stdlib.h>
     34#include <ctype.h>
     35#include <assert.h>
     36
     37#include <rtems/libio_.h>
     38
     39#include "fat.h"
     40#include "fat_fat_operations.h"
     41#include "msdos.h"
     42#include "dosfs.h"
     43
     44typedef struct {
     45  unsigned32 bytes_per_sector;
     46  unsigned32 totl_sector_cnt;
     47  unsigned32 rsvd_sector_cnt;
     48
     49  unsigned32 sectors_per_cluster;
     50  unsigned32 sectors_per_fat;
     51
     52  unsigned32 fat_start_sec;
     53  unsigned32 files_per_root_dir;
     54  unsigned32 root_dir_sectors;
     55  unsigned32 root_dir_start_sec;
     56  unsigned32 root_dir_fmt_sec_cnt;
     57  unsigned32 mbr_copy_sec; /* location of copy of mbr or 0 */
     58  unsigned32 fsinfo_sec;   /* location of fsinfo sector or 0 */
     59  unsigned8  fat_num;
     60  unsigned8  media_code;
     61  unsigned8  fattype;
     62  char       OEMName[FAT_BR_OEMNAME_SIZE+1];
     63  char       VolLabel[FAT_BR_VOLLAB_SIZE+1];
     64  boolean    VolLabel_present;
     65  unsigned32 vol_id;
     66}  msdos_format_param_t;
     67
     68/*=========================================================================*\
     69| Function:                                                                 |
     70\*-------------------------------------------------------------------------*/
     71static int msdos_format_write_sec
     72(
     73/*-------------------------------------------------------------------------*\
     74| Purpose:                                                                  |
     75|     function to write to a sector                                         |
     76+---------------------------------------------------------------------------+
     77| Input Parameters:                                                         |
     78\*-------------------------------------------------------------------------*/
     79 int         fd,                       /* file descriptor index            */
     80 unsigned32  start_sector,             /* sector number to write to        */
     81 unsigned32  sector_size,              /* size of sector                   */
     82 const char *buffer                    /* buffer with write data           */
     83 )
     84/*-------------------------------------------------------------------------*\
     85| Return Value:                                                             |
     86|    0, if success, -1 and errno if failed                                  |
     87\*=========================================================================*/
     88{
     89  int ret_val = 0;
     90
     91  if (0 > lseek(fd,((off_t)start_sector)*sector_size,SEEK_SET)) {
     92    ret_val = -1;
     93  }
     94  if (ret_val == 0) {
     95    if (0 > write(fd,buffer,sector_size)) {
     96      ret_val = -1;
     97    }
     98  }
     99
     100  return ret_val;
     101}
     102
     103/*=========================================================================*\
     104| Function:                                                                 |
     105\*-------------------------------------------------------------------------*/
     106static int msdos_format_fill_sectors
     107(
     108/*-------------------------------------------------------------------------*\
     109| Purpose:                                                                  |
     110|     function to fill sectors with byte                                    |
     111+---------------------------------------------------------------------------+
     112| Input Parameters:                                                         |
     113\*-------------------------------------------------------------------------*/
     114 int         fd,                       /* file descriptor index            */
     115 unsigned32  start_sector,             /* sector number to fill to         */
     116 unsigned32  sector_cnt,               /* number of sectors to fill to     */
     117 unsigned32  sector_size,              /* size of sector                   */
     118 const char  fill_byte                 /* byte to fill into sectors        */
     119 )
     120/*-------------------------------------------------------------------------*\
     121| Return Value:                                                             |
     122|    0, if success, -1 and errno if failed                                  |
     123\*=========================================================================*/
     124{
     125  int ret_val = 0;
     126  char *fill_buffer = NULL;
     127
     128  /*
     129   * allocate and fill buffer
     130   */
     131  if (ret_val == 0) {
     132    fill_buffer = malloc(sector_size);
     133    if (fill_buffer == NULL) {
     134      errno = ENOMEM;
     135      ret_val = -1;
     136    }
     137    else {
     138      memset(fill_buffer,fill_byte,sector_size);
     139    }
     140  }
     141  /*
     142   * write to consecutive sectors
     143   */
     144  while ((ret_val == 0) &&
     145         (sector_cnt > 0)) {
     146    ret_val = msdos_format_write_sec(fd,start_sector,sector_size,fill_buffer);
     147    start_sector++;
     148    sector_cnt--;
     149  }
     150  /*
     151   * cleanup
     152   */
     153  if (fill_buffer != NULL) {
     154    free(fill_buffer);
     155    fill_buffer = NULL;
     156  }
     157  return ret_val;
     158}
     159
     160
     161/*=========================================================================*\
     162| Function:                                                                 |
     163\*-------------------------------------------------------------------------*/
     164static int msdos_format_gen_volid
     165(
     166/*-------------------------------------------------------------------------*\
     167| Purpose:                                                                  |
     168|     function to generate a pseudo-random volume id                        |
     169+---------------------------------------------------------------------------+
     170| Input Parameters:                                                         |
     171\*-------------------------------------------------------------------------*/
     172 unsigned32 *volid_ptr                 /* volume ID return pointer         */
     173 )
     174/*-------------------------------------------------------------------------*\
     175| Return Value:                                                             |
     176|    0, if success, -1 and errno if failed                                  |
     177\*=========================================================================*/
     178{
     179  int ret_val = 0;
     180  int rc;
     181  rtems_clock_time_value time_value;
     182
     183  rc = rtems_clock_get(RTEMS_CLOCK_GET_TIME_VALUE,&time_value);
     184  if (rc == RTEMS_SUCCESSFUL) {
     185    *volid_ptr = time_value.seconds + time_value.microseconds;
     186  }
     187  else {
     188    *volid_ptr = rand();
     189  }
     190
     191  return ret_val;
     192}
     193
     194
     195/*=========================================================================*\
     196| Function:                                                                 |
     197\*-------------------------------------------------------------------------*/
     198static int msdos_format_eval_sectors_per_cluster
     199(
     200/*-------------------------------------------------------------------------*\
     201| Purpose:                                                                  |
     202|     function to check/adjust sectors_per_cluster to legal values          |
     203+---------------------------------------------------------------------------+
     204| Input Parameters:                                                         |
     205\*-------------------------------------------------------------------------*/
     206 int         fattype,                  /* type code of FAT (FAT_FAT12 ...) */
     207 unsigned32  bytes_per_sector,         /* byte count per sector (512)      */
     208 unsigned32  fatdata_sec_cnt,          /* sectors available for FAT and data */
     209 unsigned8   fat_num,                  /* number of fat copies             */
     210 unsigned32  sectors_per_cluster,      /* sectors per cluster (requested)  */
     211 unsigned32 *sectors_per_cluster_adj,  /* ret: sec per cluster (granted)   */
     212 unsigned32 *sectors_per_fat_ptr       /* ret: sectors needed for one FAT  */
     213 )
     214/*-------------------------------------------------------------------------*\
     215| Return Value:                                                             |
     216|    0, if success, -1 and errno if failed                                  |
     217\*=========================================================================*/
     218{
     219
     220  boolean finished = FALSE;
     221  int ret_val = 0;
     222  unsigned32 fatdata_cluster_cnt;
     223  unsigned32 fat_capacity;
     224  unsigned32 sectors_per_fat;
     225  unsigned32 data_cluster_cnt;
     226  /*
     227   * ensure, that maximum cluster size (32KByte) is not exceeded
     228   */
     229  while (MS_BYTES_PER_CLUSTER_LIMIT / bytes_per_sector < sectors_per_cluster) {
     230    sectors_per_cluster /= 2;
     231  }
     232 
     233  do {
     234    /*
     235     * compute number of data clusters for current data:
     236     * - compute cluster count for data AND fat
     237     * - compute storage size for FAT
     238     * - subtract from total cluster count
     239     */
     240    fatdata_cluster_cnt = fatdata_sec_cnt/sectors_per_cluster;
     241    if (fattype == FAT_FAT12) {
     242      fat_capacity = fatdata_cluster_cnt * 3 / 2;
     243    }
     244    else if (fattype == FAT_FAT16) {
     245      fat_capacity = fatdata_cluster_cnt * 2;
     246    }
     247    else { /* FAT32 */
     248      fat_capacity = fatdata_cluster_cnt * 4;
     249    }
     250
     251    sectors_per_fat = ((fat_capacity
     252                        + (bytes_per_sector - 1))
     253                       / bytes_per_sector);
     254
     255    data_cluster_cnt = (fatdata_cluster_cnt -
     256                        (((sectors_per_fat * fat_num)
     257                          + (sectors_per_cluster - 1))
     258                         / sectors_per_cluster));
     259    /*
     260     * data cluster count too big? then make sectors bigger
     261     */
     262    if (((fattype == FAT_FAT12) && (data_cluster_cnt > FAT_FAT12_MAX_CLN)) ||
     263        ((fattype == FAT_FAT16) && (data_cluster_cnt > FAT_FAT16_MAX_CLN))) {
     264      sectors_per_cluster *= 2;
     265    }
     266    else {
     267      finished = TRUE;
     268    }
     269    /*
     270     * when maximum cluster size is exceeded, we have invalid data, abort...
     271     */
     272    if ((sectors_per_cluster * bytes_per_sector)
     273        > MS_BYTES_PER_CLUSTER_LIMIT) {
     274      ret_val = EINVAL;
     275      finished = TRUE;
     276    }
     277  } while (!finished);
     278
     279  if (ret_val != 0) {
     280    set_errno_and_return_minus_one(ret_val);
     281  }
     282  else {
     283    *sectors_per_cluster_adj = sectors_per_cluster;
     284    *sectors_per_fat_ptr     = sectors_per_fat;
     285    return 0;
     286  }
     287}
     288
     289
     290/*=========================================================================*\
     291| Function:                                                                 |
     292\*-------------------------------------------------------------------------*/
     293static int msdos_format_determine_fmt_params
     294(
     295/*-------------------------------------------------------------------------*\
     296| Purpose:                                                                  |
     297|     determine parameters for formatting                                   |
     298+---------------------------------------------------------------------------+
     299| Input Parameters:                                                         |
     300\*-------------------------------------------------------------------------*/
     301 const disk_device            *dd,       /* disk device structure          */
     302 const msdos_format_request_param_t *rqdata,   /* requested fmt parameters */
     303 msdos_format_param_t         *fmt_params/* computed fmt parameters        */
     304 )
     305/*-------------------------------------------------------------------------*\
     306| Return Value:                                                             |
     307|    0, if success, -1 and errno if failed                                  |
     308\*=========================================================================*/
     309{
     310  int ret_val = 0;
     311  unsigned32 fatdata_sect_cnt;
     312  unsigned32 onebit;
     313  unsigned32 sectors_per_cluster_adj;
     314
     315  memset(fmt_params,0,sizeof(*fmt_params));
     316  /*
     317   * this one is fixed in this implementation.
     318   * At least one thing we don't have to magically guess...
     319   */
     320  if (ret_val == 0) {
     321    fmt_params->bytes_per_sector = dd->block_size;
     322    fmt_params->totl_sector_cnt  = dd->size;
     323  }
     324  /*
     325   * determine number of FATs
     326   */
     327  if (ret_val == 0) {
     328    if ((rqdata == NULL) ||
     329        (rqdata->fat_num == 0)) {
     330      fmt_params->fat_num = 2;
     331    }
     332    else if (rqdata->fat_num <= 6) {
     333      fmt_params->fat_num = rqdata->fat_num;
     334    }
     335    else {
     336      ret_val = EINVAL;
     337    }
     338  }
     339  /*
     340   * Now we get sort of a loop when determining things:
     341   * The FAT type (FAT12/16/32) is determined ONLY from the
     342   * data cluster count:
     343   * Disks with data cluster count <  4085 are FAT12.
     344   * Disks with data cluster count < 65525 are FAT16.
     345   * The rest is FAT32 (no FAT128 available yet :-)
     346   *
     347   * The number of data clusters is the
     348   * total capacity
     349   * minus reserved sectors
     350   * minus root directory ares
     351   * minus storage needed for the FAT (and its copy/copies).
     352   *
     353   * The last item once again depends on the FAT type and the cluster count.
     354   *
     355   * So here is what we do in this formatter:
     356   * - If a FAT type is requested from the caller, we try to modify
     357   * the cluster size, until the data cluster count is in range
     358   * - If no FAT type is given, we estimate a useful FAT type from
     359   * the disk capacity and then adapt the cluster size
     360   */ 
     361
     362  /*
     363   * determine characteristic values:
     364   * - number of sectors
     365   * - number of reserved sectors
     366   * - number of used sectors
     367   * - sectors per cluster
     368   */
     369  /*
     370   * determine FAT type and sectors per cluster
     371   * depends on
     372   */
     373  if (ret_val == 0) {
     374    fmt_params->sectors_per_cluster = 1;
     375    if ((rqdata != NULL) &&
     376        (rqdata->fattype == MSDOS_FMT_FAT12)) {
     377      fmt_params->fattype = FAT_FAT12;
     378    }
     379    else if ((rqdata != NULL) &&
     380             (rqdata->fattype == MSDOS_FMT_FAT16)) {
     381      fmt_params->fattype = FAT_FAT16;
     382    }
     383    else if ((rqdata != NULL) &&
     384             (rqdata->fattype == MSDOS_FMT_FAT32)) {
     385      fmt_params->fattype = FAT_FAT32;
     386    }
     387    else if ((rqdata != NULL) &&
     388             (rqdata->fattype != MSDOS_FMT_FATANY)) {
     389      ret_val = -1;
     390      errno = EINVAL;
     391    }
     392    else {
     393      /*
     394       * limiting values for disk size, fat type, sectors per cluster
     395       * NOTE: maximum sect_per_clust is arbitrarily choosen with values that
     396       * are a compromise concerning capacity and efficency
     397       */
     398      if (fmt_params->totl_sector_cnt
     399          < ((unsigned32)FAT_FAT12_MAX_CLN)*8) {
     400        fmt_params->fattype = FAT_FAT12;
     401        /* start trying with small clusters */
     402        fmt_params->sectors_per_cluster = 2;
     403      }
     404      else if (fmt_params->totl_sector_cnt
     405               < ((unsigned32)FAT_FAT16_MAX_CLN)*32) {
     406        fmt_params->fattype = FAT_FAT16;
     407        /* start trying with small clusters */
     408        fmt_params->sectors_per_cluster = 2;
     409      }
     410      else {
     411        fmt_params->fattype = FAT_FAT32;
     412        /* start trying with small clusters... */
     413        fmt_params->sectors_per_cluster = 1;
     414      }
     415    }
     416    /*
     417     * try to use user requested cluster size
     418     */
     419    if ((rqdata != NULL) &&
     420        (rqdata->sectors_per_cluster > 0)) {
     421      fmt_params->sectors_per_cluster =
     422        rqdata->sectors_per_cluster;   
     423    }
     424    /*
     425     * check sectors per cluster.
     426     * must be power of 2
     427     * must be smaller than or equal to 128
     428     * sectors_per_cluster*bytes_per_sector must not be bigger than 32K
     429     */
     430    for (onebit = 128;onebit >= 1;onebit = onebit>>1) {
     431      if (fmt_params->sectors_per_cluster > onebit) {
     432        fmt_params->sectors_per_cluster = onebit;
     433        if (fmt_params->sectors_per_cluster
     434            <= 32768L/fmt_params->bytes_per_sector) {
     435          /* value is small enough so this value is ok */
     436          onebit = 1;
     437        }
     438      }
     439    }
     440  }
     441
     442  if (ret_val == 0) {
     443    if (fmt_params->fattype == FAT_FAT32) {
     444      /* recommended: for FAT32, always set reserved sector count to 32 */
     445      fmt_params->rsvd_sector_cnt = 32;
     446      /* for FAT32, always set files per root directory 0 */
     447      fmt_params->files_per_root_dir = 0;
     448      /* location of copy of MBR */
     449      fmt_params->mbr_copy_sec = 6;
     450      /* location of fsinfo sector */
     451      fmt_params->fsinfo_sec = 1;
     452
     453    }
     454    else {
     455      /* recommended: for FAT12/FAT16, always set reserved sector count to 1 */
     456      fmt_params->rsvd_sector_cnt = 1;
     457      /* recommended: for FAT16, set files per root directory to 512 */
     458      /* for FAT12/FAT16, set files per root directory */
     459      /* must fill up an even count of sectors         */
     460      if ((rqdata != NULL) &&
     461          (rqdata->files_per_root_dir > 0)) {
     462        fmt_params->files_per_root_dir = rqdata->files_per_root_dir;
     463      }
     464      else {
     465        if (fmt_params->fattype == FAT_FAT16) {
     466          fmt_params->files_per_root_dir = 512;
     467        }
     468        else {
     469          fmt_params->files_per_root_dir = 64;
     470        }
     471      }
     472      fmt_params->files_per_root_dir = (fmt_params->files_per_root_dir +
     473                            (2*fmt_params->bytes_per_sector/
     474                             FAT_DIRENTRY_SIZE-1));
     475      fmt_params->files_per_root_dir -= (fmt_params->files_per_root_dir %
     476                             (2*fmt_params->bytes_per_sector
     477                              /FAT_DIRENTRY_SIZE));
     478    }
     479    fmt_params->root_dir_sectors =
     480      (((fmt_params->files_per_root_dir * FAT_DIRENTRY_SIZE)
     481        + fmt_params->bytes_per_sector - 1)
     482       / fmt_params->bytes_per_sector);
     483  }
     484  if (ret_val == 0) {
     485    fatdata_sect_cnt = (fmt_params->totl_sector_cnt -
     486                        fmt_params->rsvd_sector_cnt -
     487                        fmt_params->root_dir_sectors);
     488                       
     489    /*
     490     * check values to get legal arrangement of FAT type and cluster count
     491     */
     492
     493    ret_val = msdos_format_eval_sectors_per_cluster
     494      (fmt_params->fattype,
     495       fmt_params->bytes_per_sector,
     496       fatdata_sect_cnt,
     497       fmt_params->fat_num,
     498       fmt_params->sectors_per_cluster,
     499       &sectors_per_cluster_adj,
     500       &(fmt_params->sectors_per_fat));
     501    fmt_params->sectors_per_cluster = sectors_per_cluster_adj;
     502  }
     503
     504  /*
     505   * determine media code
     506   */
     507  if (ret_val == 0) {
     508    if ((rqdata != NULL) &&
     509        (rqdata->media != 0)) {
     510      const char valid_media_codes[] =
     511        {0xF0,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF};
     512      if (NULL==memchr(valid_media_codes,
     513                       rqdata->media,
     514                       sizeof(valid_media_codes))) {
     515        ret_val = -1;
     516        errno = EINVAL;
     517      }
     518      else {
     519        fmt_params->media_code = rqdata->media;
     520      }
     521    }
     522    else {
     523      fmt_params->media_code = FAT_BR_MEDIA_FIXED;
     524    }
     525  }
     526  /*
     527   * determine location and size of root directory
     528   * for formatting
     529   */
     530  if (fmt_params->root_dir_sectors > 0) {
     531    fmt_params->root_dir_start_sec =
     532      fmt_params->rsvd_sector_cnt
     533      + (fmt_params-> fat_num*fmt_params->sectors_per_fat);
     534    fmt_params->root_dir_fmt_sec_cnt = fmt_params->root_dir_sectors;
     535  }
     536  else {
     537    /*
     538     * for FAT32: root directory is in cluster 2
     539     */
     540    fmt_params->root_dir_start_sec =
     541      fmt_params->rsvd_sector_cnt
     542      + (fmt_params-> fat_num*fmt_params->sectors_per_fat);
     543    fmt_params->root_dir_fmt_sec_cnt = fmt_params->sectors_per_cluster;
     544  }
     545  /*
     546   * determine usable OEMName
     547   */
     548  if (ret_val == 0) {
     549      const char *from;
     550      char        *to = fmt_params->OEMName;
     551      int          cnt;
     552      from = "RTEMS"; /* default: make "from" point to OS Name */
     553    if ((rqdata != NULL) &&
     554        (rqdata->OEMName != NULL)) {
     555      from = rqdata->OEMName;
     556    }
     557    for (cnt = 0;
     558         cnt < (sizeof(fmt_params->OEMName)-1);
     559         cnt++) {
     560      if (isprint(*from)) {
     561        *to++ = *from++;
     562      }
     563      else {
     564        /*
     565         * non-printable character in given name, so keep stuck
     566         * at that character and replace all following characters
     567         * with a ' '
     568         */
     569        *to++=' ';
     570      }
     571      *to = '\0';
     572    }
     573  }
     574
     575  /*
     576   * determine usable Volume Label
     577   */
     578  if (ret_val == 0) {
     579      const char *from;
     580      char        *to = fmt_params->VolLabel;
     581      int          cnt;
     582      from = ""; /* default: make "from" point to empty string */
     583    if ((rqdata != NULL) &&
     584        (rqdata->VolLabel != NULL)) {
     585      from = rqdata->VolLabel;
     586      fmt_params->VolLabel_present = TRUE;
     587    }
     588    for (cnt = 0;
     589         cnt < (sizeof(fmt_params->VolLabel)-1);
     590         cnt++) {
     591      if (isprint(*from)) {
     592        *to++ = *from++;
     593      }
     594      else {
     595        /*
     596         * non-printable character in given name, so keep stuck
     597         * at that character and replace all following characters
     598         * with a ' '
     599         */
     600        *to++=' ';
     601      }
     602      *to = '\0';
     603    }
     604  }
     605     
     606  /*
     607   * determine usable Volume ID
     608   */
     609  if (ret_val == 0) {
     610    msdos_format_gen_volid(&(fmt_params->vol_id));
     611  }
     612  /*
     613   * Phuuu.... That's it.
     614   */
     615  if (ret_val != 0) {
     616    set_errno_and_return_minus_one(ret_val);
     617  }
     618  else {
     619    return 0;
     620  }
     621}
     622/*=========================================================================*\
     623| Function:                                                                 |
     624\*-------------------------------------------------------------------------*/
     625static int msdos_format_gen_mbr
     626(
     627/*-------------------------------------------------------------------------*\
     628| Purpose:                                                                  |
     629|     create master boot record content from parameter set                  |
     630+---------------------------------------------------------------------------+
     631| Input Parameters:                                                         |
     632\*-------------------------------------------------------------------------*/
     633 char mbr[],                           /* sector buffer                    */
     634 const msdos_format_param_t *fmt_params/* computed fmt parameters          */
     635 )
     636/*-------------------------------------------------------------------------*\
     637| Return Value:                                                             |
     638|    0, if success, -1 and errno if failed                                  |
     639\*=========================================================================*/
     640{
     641  unsigned32  total_sectors_num16 = 0;
     642  unsigned32  total_sectors_num32 = 0;
     643
     644  /* store total sector count in either 16 or 32 bit field in mbr */
     645  if (fmt_params->totl_sector_cnt < 0x10000) {
     646    total_sectors_num16 = fmt_params->totl_sector_cnt;
     647  }
     648  else {
     649    total_sectors_num32 = fmt_params->totl_sector_cnt;
     650  }
     651  /*
     652   * finally we are there: let's fill in the values into the MBR
     653   */
     654  memset(mbr,0,FAT_TOTAL_MBR_SIZE);
     655  /*
     656   * FIXME: fill jmpBoot and Boot code...
     657   * with 0xEB,....
     658   */
     659  /*
     660   * fill OEMName
     661   */
     662  memcpy(FAT_GET_ADDR_BR_OEMNAME(mbr),
     663         fmt_params->OEMName,
     664         FAT_BR_OEMNAME_SIZE);
     665  FAT_SET_BR_BYTES_PER_SECTOR(mbr    , fmt_params->bytes_per_sector);
     666  FAT_SET_BR_SECTORS_PER_CLUSTER(mbr , fmt_params->sectors_per_cluster);
     667  FAT_SET_BR_RESERVED_SECTORS_NUM(mbr, fmt_params->rsvd_sector_cnt);
     668 
     669  /* number of FATs on medium */
     670  FAT_SET_BR_FAT_NUM(mbr             , 2); /* standard/recommended value */
     671  FAT_SET_BR_FILES_PER_ROOT_DIR(mbr  , fmt_params->files_per_root_dir);
     672  FAT_SET_BR_TOTAL_SECTORS_NUM16(mbr , total_sectors_num16);
     673  FAT_SET_BR_MEDIA(mbr               , fmt_params->media_code);
     674
     675  FAT_SET_BR_SECTORS_PER_TRACK(mbr   , 0); /* only needed for INT13... */
     676  FAT_SET_BR_NUMBER_OF_HEADS(mbr     , 0); /* only needed for INT13... */
     677  FAT_SET_BR_HIDDEN_SECTORS(mbr      , 0); /* only needed for INT13... */
     678
     679  FAT_SET_BR_TOTAL_SECTORS_NUM32(mbr , total_sectors_num32);
     680  if (fmt_params->fattype != FAT_FAT32) {
     681    FAT_SET_BR_SECTORS_PER_FAT(mbr   ,fmt_params->sectors_per_fat);
     682    FAT_SET_BR_DRVNUM(mbr            , 0); /* only needed for INT13... */
     683    FAT_SET_BR_RSVD1(mbr             , 0); /* fill with zero */
     684    FAT_SET_BR_BOOTSIG(mbr           , FAT_BR_BOOTSIG_VAL);
     685    FAT_SET_BR_VOLID(mbr             , fmt_params->vol_id); /* volume id */
     686  memcpy(FAT_GET_ADDR_BR_VOLLAB(mbr),
     687         fmt_params->VolLabel,
     688         FAT_BR_VOLLAB_SIZE);
     689    memcpy(FAT_GET_ADDR_BR_FILSYSTYPE(mbr),
     690           (fmt_params->fattype == FAT_FAT12)
     691           ? "FAT12   "
     692           : "FAT16   ",
     693           FAT_BR_FILSYSTYPE_SIZE);
     694  }
     695  else {
     696    FAT_SET_BR_SECTORS_PER_FAT32(mbr   ,fmt_params->sectors_per_fat);
     697    FAT_SET_BR_EXT_FLAGS(mbr           , 0);
     698    FAT_SET_BR_FSVER(mbr               , 0); /* FAT32 Version:0.0 */
     699    FAT_SET_BR_FAT32_ROOT_CLUSTER(mbr  , 2); /* put root dir to cluster 2 */
     700    FAT_SET_BR_FAT32_FS_INFO_SECTOR(mbr, 1); /* Put fsinfo  to rsrvd sec 1*/
     701    FAT_SET_BR_FAT32_BK_BOOT_SECTOR(mbr, fmt_params->mbr_copy_sec ); /* Put MBR copy to rsrvd sec */
     702    memset(FAT_GET_ADDR_BR_FAT32_RESERVED(mbr),0,FAT_BR_FAT32_RESERVED_SIZE);
     703
     704    FAT_SET_BR_FAT32_DRVNUM(mbr      , 0); /* only needed for INT13... */
     705    FAT_SET_BR_FAT32_RSVD1(mbr       , 0); /* fill with zero */
     706    FAT_SET_BR_FAT32_BOOTSIG(mbr     ,FAT_BR_FAT32_BOOTSIG_VAL);
     707    FAT_SET_BR_FAT32_VOLID(mbr       , 0); /* not set */
     708    memset(FAT_GET_ADDR_BR_FAT32_VOLLAB(mbr)   ,0,FAT_BR_VOLLAB_SIZE);
     709    memcpy(FAT_GET_ADDR_BR_FAT32_FILSYSTYPE(mbr),
     710           "FAT32   ",
     711           FAT_BR_FILSYSTYPE_SIZE);
     712  }
     713  /*
     714   * add boot record signature
     715   */
     716  FAT_SET_BR_SIGNATURE(mbr,      FAT_BR_SIGNATURE_VAL);
     717
     718  /*
     719   * add jump to boot loader at start of sector
     720   */
     721  FAT_SET_VAL8(mbr,0,0xeb);
     722  FAT_SET_VAL8(mbr,1,0x3c);
     723  FAT_SET_VAL8(mbr,2,0x90);
     724  /*
     725   * FIXME: a nice little PC boot loader would be nice here.
     726   * but where can I get one for free?
     727   */
     728  /*
     729   * Phuuu.... That's it.
     730   */
     731  return 0;
     732}
     733
     734/*=========================================================================*\
     735| Function:                                                                 |
     736\*-------------------------------------------------------------------------*/
     737static int msdos_format_gen_fsinfo
     738(
     739/*-------------------------------------------------------------------------*\
     740| Purpose:                                                                  |
     741|     create FAT32 fsinfo sector                                            |
     742+---------------------------------------------------------------------------+
     743| Input Parameters:                                                         |
     744\*-------------------------------------------------------------------------*/
     745 char fsinfo[]                         /* sector buffer                    */
     746 )
     747/*-------------------------------------------------------------------------*\
     748| Return Value:                                                             |
     749|    0, if success, -1 and errno if failed                                  |
     750\*=========================================================================*/
     751{
     752
     753  /*
     754   * clear fsinfo sector data
     755   */
     756  memset(fsinfo,0,FAT_TOTAL_FSINFO_SIZE);
     757  /*
     758   * write LEADSIG, STRUCTSIG, TRAILSIG
     759   */
     760  FAT_SET_FSINFO_LEAD_SIGNATURE (fsinfo,FAT_FSINFO_LEAD_SIGNATURE_VALUE );
     761  FAT_SET_FSINFO_STRUC_SIGNATURE(fsinfo,FAT_FSINFO_STRUC_SIGNATURE_VALUE);
     762  FAT_SET_FSINFO_TRAIL_SIGNATURE(fsinfo,FAT_FSINFO_TRAIL_SIGNATURE_VALUE);
     763/*
     764 * write "empty" values for free cluster count and next cluster number
     765 */
     766  FAT_SET_FSINFO_FREE_CLUSTER_COUNT(fsinfo+FAT_FSI_INFO,
     767                                    0xffffffff);
     768  FAT_SET_FSINFO_NEXT_FREE_CLUSTER (fsinfo+FAT_FSI_INFO,
     769                                    0xffffffff);
     770  return 0;
     771}
     772
     773/*=========================================================================*\
     774| Function:                                                                 |
     775\*-------------------------------------------------------------------------*/
     776int msdos_format
     777(
     778/*-------------------------------------------------------------------------*\
     779| Purpose:                                                                  |
     780|     format device with msdos filesystem                                   |
     781+---------------------------------------------------------------------------+
     782| Input Parameters:                                                         |
     783\*-------------------------------------------------------------------------*/
     784 const char *devname,                  /* device name                      */
     785 const msdos_format_request_param_t *rqdata  /* requested fmt parameters   */
     786                                             /* set to NULL for automatic  */
     787                                             /* determination              */
     788 )
     789/*-------------------------------------------------------------------------*\
     790| Return Value:                                                             |
     791|    0, if success, -1 and errno if failed                                  |
     792\*=========================================================================*/
     793{
     794  char         tmp_sec[FAT_TOTAL_MBR_SIZE];
     795  int          rc;
     796  disk_device *dd        = NULL;
     797  struct stat  stat_buf;
     798  int          ret_val   = 0;
     799  int          fd        = -1;
     800  int          i;
     801  msdos_format_param_t fmt_params;
     802
     803  /*
     804   * sanity check on device
     805   */
     806  if (ret_val == 0) {
     807    rc = stat(devname, &stat_buf);
     808    ret_val = rc;
     809  }
     810 
     811  /* rtems feature: no block devices, all are character devices */   
     812  if ((ret_val == 0) &&
     813      (!S_ISCHR(stat_buf.st_mode))) {
     814    errno = ENOTBLK;
     815    ret_val = -1;
     816  }
     817 
     818  /* check that  device is registered as block device and lock it */
     819  if (ret_val == 0) {
     820    dd = rtems_disk_lookup(stat_buf.st_dev);
     821    if (dd == NULL) {
     822      errno = ENOTBLK;
     823      ret_val = -1;
     824    }
     825  }
     826
     827  /*
     828   * open device for writing
     829   */
     830  if (ret_val == 0) {
     831    fd = open(devname, O_WRONLY);
     832    if (fd == -1)
     833    {
     834      ret_val= -1;
     835    }   
     836  } 
     837
     838  /*
     839   * compute formatting parameters
     840   */
     841  if (ret_val == 0) {
     842    ret_val = msdos_format_determine_fmt_params(dd,rqdata,&fmt_params);
     843  }
     844  /*
     845   * if requested, write whole disk/partition with 0xe5
     846   */
     847  if ((ret_val == 0) &&
     848      (rqdata != NULL) &&
     849      !(rqdata->quick_format)) {
     850    ret_val = msdos_format_fill_sectors
     851      (fd,
     852       0,                            /* start sector */
     853       fmt_params.totl_sector_cnt,   /* sector count */
     854       fmt_params.bytes_per_sector,
     855       0xe5);
     856  }
     857  /*
     858   * create master boot record
     859   */
     860  if (ret_val == 0) {
     861    ret_val = msdos_format_gen_mbr(tmp_sec,&fmt_params);
     862  }
     863  /*
     864   * write master boot record to disk
     865   * also write copy of MBR to disk
     866   */
     867  if (ret_val == 0) {
     868    ret_val = msdos_format_write_sec(fd,
     869                                     0,
     870                                     fmt_params.bytes_per_sector,
     871                                     (void *)tmp_sec);
     872  }
     873  if ((ret_val == 0) &&
     874      (fmt_params.mbr_copy_sec != 0)) {
     875    /*
     876     * write copy of MBR
     877     */
     878    ret_val = msdos_format_write_sec(fd,
     879                                     fmt_params.mbr_copy_sec ,
     880                                     fmt_params.bytes_per_sector,
     881                                     (void *)tmp_sec);
     882  }
     883  /*
     884   * for FAT32: initialize info sector on disk
     885   */
     886  if ((ret_val == 0) &&
     887      (fmt_params.fsinfo_sec != 0)) {
     888      ret_val = msdos_format_gen_fsinfo(tmp_sec);
     889  }
     890  /*
     891   * write fsinfo sector
     892   */
     893  if ((ret_val == 0) &&
     894      (fmt_params.fsinfo_sec != 0)) {
     895    ret_val = msdos_format_write_sec(fd,
     896                                     fmt_params.fsinfo_sec,
     897                                     fmt_params.bytes_per_sector,
     898                                     (void *)tmp_sec);
     899  }
     900  /*
     901   * write FAT as all empty
     902   * -> write all FAT sectors as zero
     903   */
     904  if (ret_val == 0) {
     905    ret_val = msdos_format_fill_sectors
     906      (fd,
     907       fmt_params.rsvd_sector_cnt,                   /* start sector */
     908       fmt_params.fat_num*fmt_params.sectors_per_fat,/* sector count */
     909       fmt_params.bytes_per_sector,
     910       0x00);
     911  }
     912  /*
     913   * clear/init root directory
     914   * -> write all directory sectors as 0x00
     915   */
     916  if (ret_val == 0) {
     917    ret_val = msdos_format_fill_sectors
     918      (fd,
     919       fmt_params.root_dir_start_sec,        /* start sector */
     920       fmt_params.root_dir_fmt_sec_cnt,      /* sector count */
     921       fmt_params.bytes_per_sector,
     922       0x00);
     923  }
     924  /*
     925   * write volume label to first entry of directory
     926   */
     927  if ((ret_val == 0) && fmt_params.VolLabel_present) {
     928    memset(tmp_sec,0,sizeof(tmp_sec));
     929    memcpy(MSDOS_DIR_NAME(tmp_sec),fmt_params.VolLabel,MSDOS_SHORT_NAME_LEN);
     930    *MSDOS_DIR_ATTR(tmp_sec) = MSDOS_ATTR_VOLUME_ID;
     931    ret_val = msdos_format_write_sec
     932      (fd,
     933       fmt_params.root_dir_start_sec,
     934       fmt_params.bytes_per_sector,
     935       tmp_sec);
     936  }
     937  /*
     938   * write FAT entry 0 as (0xffffff00|Media_type)EOC,
     939   * write FAT entry 1 as EOC
     940   * allocate directory in a FAT32 FS
     941   */
     942  if ((ret_val == 0) && fmt_params.VolLabel_present){
     943    /*
     944     * empty sector: all clusters are free/do not link further on
     945     */
     946    memset(tmp_sec,0,sizeof(tmp_sec));
     947
     948    switch(fmt_params.fattype) {
     949    case FAT_FAT12:
     950      /* LSBits of FAT entry 0: media_type */
     951      FAT_SET_VAL8(tmp_sec,0,(fmt_params.media_code));
     952      /* MSBits of FAT entry 0:0xf, LSBits of FAT entry 1: LSB of EOC */
     953      FAT_SET_VAL8(tmp_sec,1,(0x0f | (FAT_FAT12_EOC << 4)));
     954      /* MSBits of FAT entry 1: MSBits of EOC */
     955      FAT_SET_VAL8(tmp_sec,2,(FAT_FAT12_EOC >> 4));
     956      break;
     957
     958    case FAT_FAT16:
     959      /* FAT entry 0: 0xff00|media_type */
     960      FAT_SET_VAL16(tmp_sec,0,0xff00|fmt_params.media_code);
     961      /* FAT entry 1: EOC */
     962      FAT_SET_VAL16(tmp_sec,2,FAT_FAT16_EOC);
     963      break;
     964
     965    case FAT_FAT32:
     966      /* FAT entry 0: 0xffffff00|media_type */
     967      FAT_SET_VAL32(tmp_sec,0,0xffffff00|fmt_params.media_code);
     968      /* FAT entry 1: EOC */
     969      FAT_SET_VAL32(tmp_sec,4,FAT_FAT32_EOC);
     970      break;
     971
     972    default:
     973      ret_val = -1;
     974      errno = EINVAL;
     975    }
     976    if (fmt_params.fattype == FAT_FAT32) {
     977      /*
     978       * only first valid cluster (cluster number 2) belongs
     979       * to root directory, and is end of chain
     980       * mark this in every copy of the FAT
     981       */
     982      FAT_SET_VAL32(tmp_sec,8,FAT_FAT32_EOC);
     983    }
     984    for (i = 0;
     985         (i < fmt_params.fat_num) && (ret_val == 0);
     986         i++) {
     987      ret_val = msdos_format_write_sec
     988        (fd,
     989         fmt_params.rsvd_sector_cnt
     990         + (i * fmt_params.sectors_per_fat),
     991         fmt_params.bytes_per_sector,
     992         tmp_sec);
     993    }
     994  }
     995  /*
     996   * cleanup:
     997   * sync and unlock disk
     998   * free any data structures (not needed now)
     999   */
     1000  if (fd != -1) {
     1001    close(fd);
     1002  }
     1003  if (dd != NULL) {
     1004    rtems_disk_release(dd);
     1005  }
     1006  return ret_val;
     1007}