Changeset 602c3d8c in mainline for uspace/app/mkfat/mkfat.c


Ignore:
Timestamp:
2011-08-16T19:51:23Z (13 years ago)
Author:
Oleg Romanenko <romanenko.oleg@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c56c4576
Parents:
ae560da
Message:

Improve HelenOS mkfat. Add option "—type 12|16|32" to toggle FAT type

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/mkfat/mkfat.c

    rae560da r602c3d8c  
    3535 * @brief       Tool for creating new FAT file systems.
    3636 *
    37  * Currently we can only create 16-bit FAT.
     37 * Currently we can create 12/16/32-bit FAT.
    3838 */
    3939
     
    5555#define div_round_up(a, b) (((a) + (b) - 1) / (b))
    5656
    57 /** Predefined file-system parameters */
     57/** Default file-system parameters */
    5858enum {
    59         sector_size             = 512,
    60         sectors_per_cluster     = 8,
    61         fat_count               = 2,
    62         reserved_clusters       = 2,
    63         media_descriptor        = 0xF8 /**< fixed disk */
     59        default_sector_size             = 512,
     60        default_sectors_per_cluster     = 4,
     61        default_fat_count               = 2,
     62        default_reserved_clusters       = 2,
     63        default_media_descriptor        = 0xF8 /**< fixed disk */
    6464};
    6565
    6666/** Configurable file-system parameters */
    6767typedef struct fat_cfg {
     68        int fat_type; /* FAT12 = 12, FAT16 = 16, FAT32 = 32 */
     69        size_t sector_size;
    6870        uint32_t total_sectors;
    6971        uint16_t root_ent_max;
    70         uint16_t addt_res_sectors;
     72        uint32_t addt_res_sectors;
     73        uint8_t sectors_per_cluster;
     74
     75        uint16_t reserved_sectors;
     76        uint32_t rootdir_sectors;
     77        uint32_t fat_sectors;
     78        uint32_t total_clusters;
     79        uint8_t fat_count;
    7180} fat_cfg_t;
    7281
    73 /** Derived file-system parameters */
    74 typedef struct fat_params {
    75         struct fat_cfg cfg;
    76         uint16_t reserved_sectors;
    77         uint16_t rootdir_sectors;
    78         uint32_t fat_sectors;
    79         uint16_t total_clusters;
    80 } fat_params_t;
    81 
    8282static void syntax_print(void);
    8383
    84 static int fat_params_compute(struct fat_cfg const *cfg,
    85     struct fat_params *par);
    86 static int fat_blocks_write(struct fat_params const *par,
    87     devmap_handle_t handle);
    88 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
     84static int fat_params_compute(struct fat_cfg *cfg);
     85static int fat_blocks_write(struct fat_cfg const *cfg, devmap_handle_t handle);
     86static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs);
    8987
    9088int main(int argc, char **argv)
    9189{
    92         struct fat_params par;
    9390        struct fat_cfg cfg;
    9491
     
    9693        char *dev_path;
    9794        devmap_handle_t handle;
    98         size_t block_size;
    9995        char *endptr;
    10096        aoff64_t dev_nblocks;
    10197
     98        cfg.sector_size = default_sector_size;
     99        cfg.sectors_per_cluster = default_sectors_per_cluster;
     100        cfg.fat_count = default_fat_count;
    102101        cfg.total_sectors = 0;
    103102        cfg.addt_res_sectors = 0;
    104103        cfg.root_ent_max = 128;
     104        cfg.fat_type = FAT16;
    105105
    106106        if (argc < 2) {
     
    111111
    112112        --argc; ++argv;
    113 
    114113        if (str_cmp(*argv, "--size") == 0) {
    115114                --argc; ++argv;
     
    130129        }
    131130
     131        if (str_cmp(*argv, "--type") == 0) {
     132                --argc; ++argv;
     133                if (*argv == NULL) {
     134                        printf(NAME ": Error, argument missing.\n");
     135                        syntax_print();
     136                        return 1;
     137                }
     138
     139                cfg.fat_type = strtol(*argv, &endptr, 10);
     140                if (*endptr != '\0') {
     141                        printf(NAME ": Error, invalid argument.\n");
     142                        syntax_print();
     143                        return 1;
     144                }
     145
     146                --argc; ++argv;
     147        }
     148
    132149        if (argc != 1) {
    133150                printf(NAME ": Error, unexpected argument.\n");
     
    137154
    138155        dev_path = *argv;
     156        printf("Device: %s\n", dev_path);
    139157
    140158        rc = devmap_device_get_handle(dev_path, &handle, 0);
     
    150168        }
    151169
    152         rc = block_get_bsize(handle, &block_size);
     170        rc = block_get_bsize(handle, &cfg.sector_size);
    153171        if (rc != EOK) {
    154172                printf(NAME ": Error determining device block size.\n");
     
    162180                printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n",
    163181                    dev_nblocks);
     182                printf("Device total size: %lld Mb\n", dev_nblocks*cfg.sector_size/(1024*1024));
    164183                cfg.total_sectors = dev_nblocks;
    165184        }
    166185
    167         if (block_size != 512) {
    168                 printf(NAME ": Error. Device block size is not 512 bytes.\n");
     186        if (cfg.fat_type == FAT12 && cfg.sector_size != 512) {
     187                printf(NAME ": Error. Device block size is not 512 bytes for FAT12 file system.\n");
    169188                return 2;
    170189        }
     
    175194        }
    176195
    177         printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
    178 
    179         rc = fat_params_compute(&cfg, &par);
     196        printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
     197
     198        rc = fat_params_compute(&cfg);
    180199        if (rc != EOK) {
    181200                printf(NAME ": Invalid file-system parameters.\n");
     
    183202        }
    184203
    185         rc = fat_blocks_write(&par, handle);
     204        rc = fat_blocks_write(&cfg, handle);
    186205        if (rc != EOK) {
    187206                printf(NAME ": Error writing device.\n");
     
    197216static void syntax_print(void)
    198217{
    199         printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
     218        printf("syntax: mkfat32 [--size <sectors>] [--type 12|16|32] <device_name>\n");
    200219}
    201220
     
    205224 * file system params.
    206225 */
    207 static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
     226static int fat_params_compute(struct fat_cfg *cfg)
    208227{
    209228        uint32_t fat_bytes;
     
    211230
    212231        /*
    213          * Make a conservative guess on the FAT size needed for the file
    214          * system. The optimum could be potentially smaller since we
    215          * do not subtract size of the FAT itself when computing the
    216          * size of the data region.
    217          */
    218 
    219         par->reserved_sectors = 1 + cfg->addt_res_sectors;
    220         par->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
    221             sector_size);
    222         non_data_sectors_lb = par->reserved_sectors + par->rootdir_sectors;
    223 
    224         par->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
    225             sectors_per_cluster);
    226 
    227         fat_bytes = (par->total_clusters + 2) * 2;
    228         par->fat_sectors = div_round_up(fat_bytes, sector_size);
    229 
    230         par->cfg = *cfg;
     232     * Make a conservative guess on the FAT size needed for the file
     233     * system. The optimum could be potentially smaller since we
     234     * do not subtract size of the FAT itself when computing the
     235     * size of the data region.
     236     */
     237
     238        if (cfg->fat_type == FAT12)
     239                cfg->sectors_per_cluster = 1;
     240
     241        cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
     242        if (cfg->fat_type != FAT32) {
     243                cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     244                        cfg->sector_size);
     245        }
     246        else
     247                cfg->rootdir_sectors = 0;
     248        non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
     249
     250        cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     251            cfg->sectors_per_cluster);
     252
     253        if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
     254                (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
     255                cfg->total_clusters > FAT16_CLST_MAX)) ||
     256            (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
     257                return ENOSPC;
     258
     259        fat_bytes = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type);
     260        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
    231261
    232262        return EOK;
     
    234264
    235265/** Create file system with the given parameters. */
    236 static int fat_blocks_write(struct fat_params const *par, devmap_handle_t handle)
     266static int fat_blocks_write(struct fat_cfg const *cfg, devmap_handle_t handle)
    237267{
    238268        aoff64_t addr;
     
    243273        struct fat_bs bs;
    244274
    245         fat_bootsec_create(par, &bs);
     275        fat_bootsec_create(cfg, &bs);
    246276
    247277        rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
     
    251281        addr = BS_BLOCK + 1;
    252282
    253         buffer = calloc(sector_size, 1);
     283        buffer = calloc(cfg->sector_size, 1);
    254284        if (buffer == NULL)
    255285                return ENOMEM;
     286        memset(buffer, 0, cfg->sector_size);
    256287
    257288        /* Reserved sectors */
    258         for (i = 0; i < par->reserved_sectors - 1; ++i) {
     289        for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    259290                rc = block_write_direct(handle, addr, 1, buffer);
    260291                if (rc != EOK)
     
    265296
    266297        /* File allocation tables */
    267         for (i = 0; i < fat_count; ++i) {
     298        for (i = 0; i < cfg->fat_count; ++i) {
    268299                printf("Writing allocation table %d.\n", i + 1);
    269300
    270                 for (j = 0; j < par->fat_sectors; ++j) {
    271                         memset(buffer, 0, sector_size);
     301                for (j = 0; j < cfg->fat_sectors; ++j) {
     302                        memset(buffer, 0, cfg->sector_size);
    272303                        if (j == 0) {
    273                                 buffer[0] = media_descriptor;
     304                                buffer[0] = default_media_descriptor;
    274305                                buffer[1] = 0xFF;
    275306                                buffer[2] = 0xFF;
    276                                 buffer[3] = 0xFF;
     307                                if (cfg->fat_type == FAT16) {
     308                                        buffer[3] = 0xFF;
     309                                } else if (cfg->fat_type == FAT32) {
     310                                        buffer[3] = 0x0F;
     311                                        buffer[4] = 0xFF;
     312                                        buffer[5] = 0xFF;
     313                                        buffer[6] = 0xFF;
     314                                        buffer[7] = 0x0F;
     315                                        buffer[8] = 0xF8;
     316                                        buffer[9] = 0xFF;
     317                                        buffer[10] = 0xFF;
     318                                        buffer[11] = 0x0F;
     319                                }
    277320                        }
    278321
     
    285328        }
    286329
     330        /* Root directory */
    287331        printf("Writing root directory.\n");
    288 
    289         memset(buffer, 0, sector_size);
    290 
    291         /* Root directory */
    292         for (i = 0; i < par->rootdir_sectors; ++i) {
    293                 rc = block_write_direct(handle, addr, 1, buffer);
    294                 if (rc != EOK)
    295                         return EIO;
    296 
    297                 ++addr;
     332        memset(buffer, 0, cfg->sector_size);
     333        if (cfg->fat_type != FAT32) {
     334                size_t idx;
     335                for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     336                        rc = block_write_direct(handle, addr, 1, buffer);
     337                        if (rc != EOK)
     338                                return EIO;
     339
     340                        ++addr;
     341                }
     342        } else {
     343                for (i=0; i<cfg->sectors_per_cluster; i++) {
     344                        rc = block_write_direct(handle, addr, 1, buffer);
     345                        if (rc != EOK)
     346                                return EIO;
     347
     348                        ++addr;
     349                }       
    298350        }
    299351
     
    304356
    305357/** Construct boot sector with the given parameters. */
    306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
     358static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    307359{
    308360        memset(bs, 0, sizeof(*bs));
     
    315367
    316368        /* BIOS Parameter Block */
    317         bs->bps = host2uint16_t_le(sector_size);
    318         bs->spc = sectors_per_cluster;
    319         bs->rscnt = host2uint16_t_le(par->reserved_sectors);
    320         bs->fatcnt = fat_count;
    321         bs->root_ent_max = host2uint16_t_le(par->cfg.root_ent_max);
    322 
    323         if (par->cfg.total_sectors < 0x10000)
    324                 bs->totsec16 = host2uint16_t_le(par->cfg.total_sectors);
    325         else
    326                 bs->totsec16 = host2uint16_t_le(0);
    327 
    328         bs->mdesc = media_descriptor;
    329         bs->sec_per_fat = host2uint16_t_le(par->fat_sectors);
     369        bs->bps = host2uint16_t_le(cfg->sector_size);
     370        bs->spc = cfg->sectors_per_cluster;
     371        bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
     372        bs->fatcnt = cfg->fat_count;
     373        bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
     374
     375        if (cfg->total_sectors < 0x10000) {
     376                bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
     377                bs->totsec32 = 0;
     378        } else {
     379                bs->totsec16 = 0;
     380                bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
     381        }
     382
     383        bs->mdesc = default_media_descriptor;
    330384        bs->sec_per_track = host2uint16_t_le(63);
     385        bs->signature = host2uint16_t_be(0x55AA);
    331386        bs->headcnt = host2uint16_t_le(6);
    332387        bs->hidden_sec = host2uint32_t_le(0);
    333388
    334         if (par->cfg.total_sectors >= 0x10000)
    335                 bs->totsec32 = host2uint32_t_le(par->cfg.total_sectors);
    336         else
    337                 bs->totsec32 = host2uint32_t_le(0);
    338 
    339         /* Extended BPB */
    340         bs->pdn = 0x80;
    341         bs->ebs = 0x29;
    342         bs->id = host2uint32_t_be(0x12345678);
    343 
    344         memcpy(bs->label, "HELENOS_NEW", 11);
    345         memcpy(bs->type, "FAT16   ", 8);
    346         bs->signature = host2uint16_t_be(0x55AA);
     389        if (cfg->fat_type == FAT32) {
     390                bs->sec_per_fat = 0;
     391                bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
     392
     393                bs->fat32.pdn = 0x80;
     394                bs->fat32.ebs = 0x29;
     395                bs->fat32.id = host2uint32_t_be(0x12345678);
     396                bs->fat32.root_cluster = 2;
     397
     398                memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     399                memcpy(bs->fat32.type, "FAT32   ", 8);
     400        } else {
     401                bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
     402                bs->pdn = 0x80;
     403                bs->ebs = 0x29;
     404                bs->id = host2uint32_t_be(0x12345678);
     405
     406                memcpy(bs->label, "HELENOS_NEW", 11);
     407                memcpy(bs->type, "FAT   ", 8);
     408        }
    347409}
    348410
Note: See TracChangeset for help on using the changeset viewer.