Ignore:
File:
1 edited

Legend:

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

    r15f3c3f r7234617  
    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
     
    4242#include <libblock.h>
    4343#include <mem.h>
    44 #include <loc.h>
     44#include <devmap.h>
    4545#include <byteorder.h>
    4646#include <sys/types.h>
     
    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, 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
    9592        int rc;
    9693        char *dev_path;
    97         service_id_t service_id;
    98         size_t block_size;
     94        devmap_handle_t handle;
    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;
    139 
    140         rc = loc_service_get_id(dev_path, &service_id, 0);
     156        printf("Device: %s\n", dev_path);
     157
     158        rc = devmap_device_get_handle(dev_path, &handle, 0);
    141159        if (rc != EOK) {
    142160                printf(NAME ": Error resolving device `%s'.\n", dev_path);
     
    144162        }
    145163
    146         rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
     164        rc = block_init(EXCHANGE_SERIALIZE, handle, 2048);
    147165        if (rc != EOK)  {
    148166                printf(NAME ": Error initializing libblock.\n");
     
    150168        }
    151169
    152         rc = block_get_bsize(service_id, &block_size);
     170        rc = block_get_bsize(handle, &cfg.sector_size);
    153171        if (rc != EOK) {
    154172                printf(NAME ": Error determining device block size.\n");
     
    156174        }
    157175
    158         rc = block_get_nblocks(service_id, &dev_nblocks);
     176        rc = block_get_nblocks(handle, &dev_nblocks);
    159177        if (rc != EOK) {
    160178                printf(NAME ": Warning, failed to obtain block device size.\n");
     
    165183        }
    166184
    167         if (block_size != 512) {
    168                 printf(NAME ": Error. Device block size is not 512 bytes.\n");
     185        if (cfg.fat_type == FAT12 && cfg.sector_size != 512) {
     186                printf(NAME ": Error. Device block size is not 512 bytes for FAT12 file system.\n");
    169187                return 2;
    170188        }
     
    175193        }
    176194
    177         printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
    178 
    179         rc = fat_params_compute(&cfg, &par);
     195        printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
     196
     197        rc = fat_params_compute(&cfg);
    180198        if (rc != EOK) {
    181199                printf(NAME ": Invalid file-system parameters.\n");
     
    183201        }
    184202
    185         rc = fat_blocks_write(&par, service_id);
     203        rc = fat_blocks_write(&cfg, handle);
    186204        if (rc != EOK) {
    187205                printf(NAME ": Error writing device.\n");
     
    189207        }
    190208
    191         block_fini(service_id);
     209        block_fini(handle);
    192210        printf("Success.\n");
    193211
     
    197215static void syntax_print(void)
    198216{
    199         printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
     217        printf("syntax: mkfat32 [--size <sectors>] [--type 12|16|32] <device_name>\n");
    200218}
    201219
     
    205223 * file system params.
    206224 */
    207 static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
     225static int fat_params_compute(struct fat_cfg *cfg)
    208226{
    209227        uint32_t fat_bytes;
     
    211229
    212230        /*
    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;
     231     * Make a conservative guess on the FAT size needed for the file
     232     * system. The optimum could be potentially smaller since we
     233     * do not subtract size of the FAT itself when computing the
     234     * size of the data region.
     235     */
     236
     237        if (cfg->fat_type == FAT12)
     238                cfg->sectors_per_cluster = 1;
     239
     240        cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
     241        if (cfg->fat_type != FAT32) {
     242                cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     243                        cfg->sector_size);
     244        }
     245        else
     246                cfg->rootdir_sectors = 0;
     247        non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
     248
     249        cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     250            cfg->sectors_per_cluster);
     251
     252        if ((cfg->fat_type == FAT12 && cfg->total_clusters > FAT12_CLST_MAX) ||
     253                (cfg->fat_type == FAT16 && (cfg->total_clusters <= FAT12_CLST_MAX ||
     254                cfg->total_clusters > FAT16_CLST_MAX)) ||
     255            (cfg->fat_type == FAT32 && cfg->total_clusters <= FAT16_CLST_MAX))
     256                return ENOSPC;
     257
     258        fat_bytes = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type);
     259        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
    231260
    232261        return EOK;
     
    234263
    235264/** Create file system with the given parameters. */
    236 static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
     265static int fat_blocks_write(struct fat_cfg const *cfg, devmap_handle_t handle)
    237266{
    238267        aoff64_t addr;
     
    243272        struct fat_bs bs;
    244273
    245         fat_bootsec_create(par, &bs);
    246 
    247         rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     274        fat_bootsec_create(cfg, &bs);
     275
     276        rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
    248277        if (rc != EOK)
    249278                return EIO;
     
    251280        addr = BS_BLOCK + 1;
    252281
    253         buffer = calloc(sector_size, 1);
     282        buffer = calloc(cfg->sector_size, 1);
    254283        if (buffer == NULL)
    255284                return ENOMEM;
     285        memset(buffer, 0, cfg->sector_size);
    256286
    257287        /* Reserved sectors */
    258         for (i = 0; i < par->reserved_sectors - 1; ++i) {
    259                 rc = block_write_direct(service_id, addr, 1, buffer);
     288        for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
     289                rc = block_write_direct(handle, addr, 1, buffer);
    260290                if (rc != EOK)
    261291                        return EIO;
     
    265295
    266296        /* File allocation tables */
    267         for (i = 0; i < fat_count; ++i) {
     297        for (i = 0; i < cfg->fat_count; ++i) {
    268298                printf("Writing allocation table %d.\n", i + 1);
    269299
    270                 for (j = 0; j < par->fat_sectors; ++j) {
    271                         memset(buffer, 0, sector_size);
     300                for (j = 0; j < cfg->fat_sectors; ++j) {
     301                        memset(buffer, 0, cfg->sector_size);
    272302                        if (j == 0) {
    273                                 buffer[0] = media_descriptor;
     303                                buffer[0] = default_media_descriptor;
    274304                                buffer[1] = 0xFF;
    275305                                buffer[2] = 0xFF;
    276                                 buffer[3] = 0xFF;
     306                                if (cfg->fat_type == FAT16) {
     307                                        buffer[3] = 0xFF;
     308                                } else if (cfg->fat_type == FAT32) {
     309                                        buffer[3] = 0x0F;
     310                                        buffer[4] = 0xFF;
     311                                        buffer[5] = 0xFF;
     312                                        buffer[6] = 0xFF;
     313                                        buffer[7] = 0x0F;
     314                                        buffer[8] = 0xF8;
     315                                        buffer[9] = 0xFF;
     316                                        buffer[10] = 0xFF;
     317                                        buffer[11] = 0x0F;
     318                                }
    277319                        }
    278320
    279                         rc = block_write_direct(service_id, addr, 1, buffer);
     321                        rc = block_write_direct(handle, addr, 1, buffer);
    280322                        if (rc != EOK)
    281323                                return EIO;
     
    285327        }
    286328
     329        /* Root directory */
    287330        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;
     331        memset(buffer, 0, cfg->sector_size);
     332        if (cfg->fat_type != FAT32) {
     333                size_t idx;
     334                for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     335                        rc = block_write_direct(handle, addr, 1, buffer);
     336                        if (rc != EOK)
     337                                return EIO;
     338
     339                        ++addr;
     340                }
     341        } else {
     342                for (i=0; i<cfg->sectors_per_cluster; i++) {
     343                        rc = block_write_direct(handle, addr, 1, buffer);
     344                        if (rc != EOK)
     345                                return EIO;
     346
     347                        ++addr;
     348                }       
    298349        }
    299350
     
    304355
    305356/** Construct boot sector with the given parameters. */
    306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
     357static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    307358{
    308359        memset(bs, 0, sizeof(*bs));
     
    315366
    316367        /* 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);
     368        bs->bps = host2uint16_t_le(cfg->sector_size);
     369        bs->spc = cfg->sectors_per_cluster;
     370        bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
     371        bs->fatcnt = cfg->fat_count;
     372        bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
     373
     374        if (cfg->total_sectors < 0x10000) {
     375                bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
     376                bs->totsec32 = 0;
     377        } else {
     378                bs->totsec16 = 0;
     379                bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
     380        }
     381
     382        bs->mdesc = default_media_descriptor;
    330383        bs->sec_per_track = host2uint16_t_le(63);
     384        bs->signature = host2uint16_t_be(0x55AA);
    331385        bs->headcnt = host2uint16_t_le(6);
    332386        bs->hidden_sec = host2uint32_t_le(0);
    333387
    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);
     388        if (cfg->fat_type == FAT32) {
     389                bs->sec_per_fat = 0;
     390                bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
     391
     392                bs->fat32.pdn = 0x80;
     393                bs->fat32.ebs = 0x29;
     394                bs->fat32.id = host2uint32_t_be(0x12345678);
     395                bs->fat32.root_cluster = 2;
     396
     397                memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     398                memcpy(bs->fat32.type, "FAT32   ", 8);
     399        } else {
     400                bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
     401                bs->pdn = 0x80;
     402                bs->ebs = 0x29;
     403                bs->id = host2uint32_t_be(0x12345678);
     404
     405                memcpy(bs->label, "HELENOS_NEW", 11);
     406                memcpy(bs->type, "FAT   ", 8);
     407        }
    347408}
    348409
Note: See TracChangeset for help on using the changeset viewer.