Changeset c05642d in mainline for uspace/app/mkfat/mkfat.c


Ignore:
Timestamp:
2011-09-07T00:03:26Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5081276
Parents:
bb74dabe (diff), 038b289 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

    rbb74dabe rc05642d  
    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     service_id_t service_id);
    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, service_id_t service_id);
     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        service_id_t service_id;
    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 = loc_service_get_id(dev_path, &service_id, 0);
     
    150168        }
    151169
    152         rc = block_get_bsize(service_id, &block_size);
     170        rc = block_get_bsize(service_id, &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);
    164                 cfg.total_sectors = dev_nblocks;
    165         }
    166 
    167         if (block_size != 512) {
    168                 printf(NAME ": Error. Device block size is not 512 bytes.\n");
    169                 return 2;
     182                if (!cfg.total_sectors || dev_nblocks < cfg.total_sectors)
     183                        cfg.total_sectors = dev_nblocks;
    170184        }
    171185
     
    175189        }
    176190
    177         printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
    178 
    179         rc = fat_params_compute(&cfg, &par);
     191        if (cfg.fat_type != FAT12 && cfg.fat_type != FAT16 && cfg.fat_type != FAT32) {
     192                printf(NAME ": Error. Unknown FAT type.\n");
     193                return 2;
     194        }
     195
     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, service_id);
     204        rc = fat_blocks_write(&cfg, service_id);
    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: mkfat [--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        cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
     239        if (cfg->fat_type != FAT32) {
     240                cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     241                        cfg->sector_size);
     242        } else
     243                cfg->rootdir_sectors = 0;
     244        non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
     245
     246        cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     247            cfg->sectors_per_cluster);
     248
     249        if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
     250            (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
     251            cfg->total_clusters > FAT16_CLST_MAX)) ||
     252            (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
     253                return ENOSPC;
     254
     255        fat_bytes = div_round_up((cfg->total_clusters + 2) *
     256            FAT_CLUSTER_DOUBLE_SIZE(cfg->fat_type), 2);
     257        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
    231258
    232259        return EOK;
     
    234261
    235262/** Create file system with the given parameters. */
    236 static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
     263static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id)
    237264{
    238265        aoff64_t addr;
     
    243270        struct fat_bs bs;
    244271
    245         fat_bootsec_create(par, &bs);
     272        fat_bootsec_create(cfg, &bs);
    246273
    247274        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     
    251278        addr = BS_BLOCK + 1;
    252279
    253         buffer = calloc(sector_size, 1);
     280        buffer = calloc(cfg->sector_size, 1);
    254281        if (buffer == NULL)
    255282                return ENOMEM;
     283        memset(buffer, 0, cfg->sector_size);
    256284
    257285        /* Reserved sectors */
    258         for (i = 0; i < par->reserved_sectors - 1; ++i) {
     286        for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    259287                rc = block_write_direct(service_id, addr, 1, buffer);
    260288                if (rc != EOK)
     
    265293
    266294        /* File allocation tables */
    267         for (i = 0; i < fat_count; ++i) {
     295        for (i = 0; i < cfg->fat_count; ++i) {
    268296                printf("Writing allocation table %d.\n", i + 1);
    269297
    270                 for (j = 0; j < par->fat_sectors; ++j) {
    271                         memset(buffer, 0, sector_size);
     298                for (j = 0; j < cfg->fat_sectors; ++j) {
     299                        memset(buffer, 0, cfg->sector_size);
    272300                        if (j == 0) {
    273                                 buffer[0] = media_descriptor;
     301                                buffer[0] = default_media_descriptor;
    274302                                buffer[1] = 0xFF;
    275303                                buffer[2] = 0xFF;
    276                                 buffer[3] = 0xFF;
     304                                if (cfg->fat_type == FAT16) {
     305                                        buffer[3] = 0xFF;
     306                                } else if (cfg->fat_type == FAT32) {
     307                                        buffer[3] = 0x0F;
     308                                        buffer[4] = 0xFF;
     309                                        buffer[5] = 0xFF;
     310                                        buffer[6] = 0xFF;
     311                                        buffer[7] = 0x0F;
     312                                        buffer[8] = 0xF8;
     313                                        buffer[9] = 0xFF;
     314                                        buffer[10] = 0xFF;
     315                                        buffer[11] = 0x0F;
     316                                }
    277317                        }
    278318
     
    285325        }
    286326
     327        /* Root directory */
    287328        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(service_id, addr, 1, buffer);
    294                 if (rc != EOK)
    295                         return EIO;
    296 
    297                 ++addr;
     329        memset(buffer, 0, cfg->sector_size);
     330        if (cfg->fat_type != FAT32) {
     331                size_t idx;
     332                for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     333                        rc = block_write_direct(service_id, addr, 1, buffer);
     334                        if (rc != EOK)
     335                                return EIO;
     336
     337                        ++addr;
     338                }
     339        } else {
     340                for (i = 0; i < cfg->sectors_per_cluster; i++) {
     341                        rc = block_write_direct(service_id, addr, 1, buffer);
     342                        if (rc != EOK)
     343                                return EIO;
     344
     345                        ++addr;
     346                }       
    298347        }
    299348
     
    304353
    305354/** Construct boot sector with the given parameters. */
    306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
     355static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    307356{
    308357        memset(bs, 0, sizeof(*bs));
     
    315364
    316365        /* 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);
     366        bs->bps = host2uint16_t_le(cfg->sector_size);
     367        bs->spc = cfg->sectors_per_cluster;
     368        bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
     369        bs->fatcnt = cfg->fat_count;
     370        bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
     371
     372        if (cfg->total_sectors < 0x10000) {
     373                bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
     374                bs->totsec32 = 0;
     375        } else {
     376                bs->totsec16 = 0;
     377                bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
     378        }
     379
     380        bs->mdesc = default_media_descriptor;
    330381        bs->sec_per_track = host2uint16_t_le(63);
     382        bs->signature = host2uint16_t_be(0x55AA);
    331383        bs->headcnt = host2uint16_t_le(6);
    332384        bs->hidden_sec = host2uint32_t_le(0);
    333385
    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);
     386        if (cfg->fat_type == FAT32) {
     387                bs->sec_per_fat = 0;
     388                bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
     389
     390                bs->fat32.pdn = 0x80;
     391                bs->fat32.ebs = 0x29;
     392                bs->fat32.id = host2uint32_t_be(0x12345678);
     393                bs->fat32.root_cluster = 2;
     394
     395                memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     396                memcpy(bs->fat32.type, "FAT32   ", 8);
     397        } else {
     398                bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
     399                bs->pdn = 0x80;
     400                bs->ebs = 0x29;
     401                bs->id = host2uint32_t_be(0x12345678);
     402
     403                memcpy(bs->label, "HELENOS_NEW", 11);
     404                memcpy(bs->type, "FAT   ", 8);
     405        }
    347406}
    348407
Note: See TracChangeset for help on using the changeset viewer.