Ignore:
File:
1 edited

Legend:

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

    r8d2dd7f2 r2456fd0  
    3838 */
    3939
     40#include <ctype.h>
    4041#include <stdio.h>
    4142#include <stdlib.h>
     
    4546#include <loc.h>
    4647#include <byteorder.h>
    47 #include <sys/typefmt.h>
    4848#include <inttypes.h>
    4949#include <errno.h>
    5050#include "fat.h"
     51#include "fat_dentry.h"
    5152
    5253#define NAME    "mkfat"
     54
     55#define LABEL_NONAME "NO NAME"
    5356
    5457/** Divide and round up. */
     
    7881        uint32_t total_clusters;
    7982        uint8_t fat_count;
     83        const char *label;
    8084} fat_cfg_t;
    8185
     
    103107        cfg.root_ent_max = 128;
    104108        cfg.fat_type = FATAUTO;
     109        cfg.label = NULL;
    105110
    106111        if (argc < 2) {
     
    111116
    112117        --argc; ++argv;
    113         if (str_cmp(*argv, "--size") == 0) {
    114                 --argc; ++argv;
    115                 if (*argv == NULL) {
    116                         printf(NAME ": Error, argument missing.\n");
    117                         syntax_print();
    118                         return 1;
     118
     119        while (*argv[0] == '-') {
     120                if (str_cmp(*argv, "--size") == 0) {
     121                        --argc; ++argv;
     122                        if (*argv == NULL) {
     123                                printf(NAME ": Error, argument missing.\n");
     124                                syntax_print();
     125                                return 1;
     126                        }
     127
     128                        cfg.total_sectors = strtol(*argv, &endptr, 10);
     129                        if (*endptr != '\0') {
     130                                printf(NAME ": Error, invalid argument.\n");
     131                                syntax_print();
     132                                return 1;
     133                        }
     134
     135                        --argc; ++argv;
    119136                }
    120137
    121                 cfg.total_sectors = strtol(*argv, &endptr, 10);
    122                 if (*endptr != '\0') {
    123                         printf(NAME ": Error, invalid argument.\n");
    124                         syntax_print();
    125                         return 1;
     138                if (str_cmp(*argv, "--type") == 0) {
     139                        --argc; ++argv;
     140                        if (*argv == NULL) {
     141                                printf(NAME ": Error, argument missing.\n");
     142                                syntax_print();
     143                                return 1;
     144                        }
     145
     146                        cfg.fat_type = strtol(*argv, &endptr, 10);
     147                        if (*endptr != '\0') {
     148                                printf(NAME ": Error, invalid argument.\n");
     149                                syntax_print();
     150                                return 1;
     151                        }
     152
     153                        --argc; ++argv;
    126154                }
    127155
    128                 --argc; ++argv;
    129         }
    130 
    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;
     156                if (str_cmp(*argv, "--label") == 0) {
     157                        --argc; ++argv;
     158                        if (*argv == NULL) {
     159                                printf(NAME ": Error, argument missing.\n");
     160                                syntax_print();
     161                                return 1;
     162                        }
     163
     164                        cfg.label = *argv;
     165
     166                        --argc; ++argv;
    137167                }
    138168
    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;
     169                if (str_cmp(*argv, "-") == 0) {
     170                        --argc; ++argv;
     171                        break;
    144172                }
    145 
    146                 --argc; ++argv;
    147173        }
    148174
     
    195221        }
    196222
    197         printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
     223        printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
    198224
    199225        rc = fat_params_compute(&cfg);
     
    203229        }
    204230
     231        printf(NAME ": Filesystem type FAT%d.\n", cfg.fat_type);
     232
    205233        rc = fat_blocks_write(&cfg, service_id);
    206234        if (rc != EOK) {
     
    217245static void syntax_print(void)
    218246{
    219         printf("syntax: mkfat [--size <sectors>] [--type 12|16|32] <device_name>\n");
     247        printf("syntax: mkfat [<options>...] <device_name>\n");
     248        printf("options:\n"
     249            "\t--size <sectors> Filesystem size, overrides device size\n"
     250            "\t--type 12|16|32  FAT type (auto-detected by default)\n"
     251            "\t--label <label>  Volume label\n");
     252}
     253
     254static int fat_label_encode(void *dest, const char *src)
     255{
     256        int i;
     257        const char *sp;
     258        uint8_t *dp;
     259
     260        i = 0;
     261        sp = src;
     262        dp = (uint8_t *)dest;
     263
     264        while (*sp != '\0' && i < FAT_VOLLABEL_LEN) {
     265                if (!ascii_check(*sp))
     266                        return EINVAL;
     267                if (dp != NULL)
     268                        dp[i] = toupper(*sp);
     269                ++i; ++sp;
     270        }
     271
     272        while (i < FAT_VOLLABEL_LEN) {
     273                if (dp != NULL)
     274                        dp[i] = FAT_PAD;
     275                ++i;
     276        }
     277
     278        return EOK;
    220279}
    221280
     
    228287{
    229288        uint32_t fat_bytes;
     289        uint32_t non_data_sectors_lb_16;
    230290        uint32_t non_data_sectors_lb;
     291        uint32_t rd_sectors;
     292        uint32_t tot_clust_16;
    231293
    232294        /*
     
    234296         * system. The optimum could be potentially smaller since we
    235297         * do not subtract size of the FAT itself when computing the
    236          * size of the data region.
     298         * size of the data region. Also the root dir area might not
     299         * need FAT entries if we decide to make a FAT32.
    237300         */
    238301
    239302        cfg->reserved_sectors = 1 + cfg->addt_res_sectors;
    240         if (cfg->fat_type != FAT32) {
    241                 cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
    242                         cfg->sector_size);
    243         } else
    244                 cfg->rootdir_sectors = 0;
    245         non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
    246 
    247         cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     303
     304        /* Only correct for FAT12/16 (FAT32 has root dir stored in clusters */
     305        rd_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     306                cfg->sector_size);
     307        non_data_sectors_lb_16 = cfg->reserved_sectors + rd_sectors;
     308
     309        /* Only correct for FAT12/16 */
     310        tot_clust_16 = div_round_up(cfg->total_sectors - non_data_sectors_lb_16,
    248311            cfg->sectors_per_cluster);
    249312
    250         if (cfg->total_clusters <= FAT12_CLST_MAX) {
     313        /* Now detect FAT type */
     314        if (tot_clust_16 <= FAT12_CLST_MAX) {
    251315                if (cfg->fat_type == FATAUTO)
    252316                        cfg->fat_type = FAT12;
    253317                else if (cfg->fat_type != FAT12)
    254318                        return EINVAL;
    255         } else if (cfg->total_clusters <= FAT16_CLST_MAX) {
     319        } else if (tot_clust_16 <= FAT16_CLST_MAX) {
    256320                if (cfg->fat_type == FATAUTO)
    257321                        cfg->fat_type = FAT16;
     
    265329        }
    266330
     331        /* Actual root directory size, non-data sectors */
     332        if (cfg->fat_type != FAT32) {
     333                cfg->rootdir_sectors = div_round_up(cfg->root_ent_max * DIRENT_SIZE,
     334                        cfg->sector_size);
     335                non_data_sectors_lb = cfg->reserved_sectors + cfg->rootdir_sectors;
     336
     337        } else {
     338                /* We create a single-cluster root dir */
     339                cfg->rootdir_sectors = cfg->sectors_per_cluster;
     340                non_data_sectors_lb = cfg->reserved_sectors;
     341        }
     342
     343        /* Actual total number of clusters */
     344        cfg->total_clusters = div_round_up(cfg->total_sectors - non_data_sectors_lb,
     345            cfg->sectors_per_cluster);
     346
    267347        fat_bytes = div_round_up((cfg->total_clusters + 2) *
    268348            FAT_CLUSTER_DOUBLE_SIZE(cfg->fat_type), 2);
    269349        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
     350
     351        if (cfg->label != NULL && fat_label_encode(NULL, cfg->label) != EOK)
     352                return EINVAL;
    270353
    271354        return EOK;
     
    281364        int rc;
    282365        struct fat_bs bs;
     366        fat_dentry_t *de;
    283367
    284368        fat_bootsec_create(cfg, &bs);
     
    340424        printf("Writing root directory.\n");
    341425        memset(buffer, 0, cfg->sector_size);
    342         if (cfg->fat_type != FAT32) {
    343                 size_t idx;
    344                 for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
    345                         rc = block_write_direct(service_id, addr, 1, buffer);
    346                         if (rc != EOK)
    347                                 return EIO;
    348 
    349                         ++addr;
     426        de = (fat_dentry_t *)buffer;
     427        size_t idx;
     428        for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     429
     430                if (idx == 0 && cfg->label != NULL) {
     431                        /* Set up volume label entry */
     432                        (void) fat_label_encode(&de->name, cfg->label);
     433                        de->attr = FAT_ATTR_VOLLABEL;
     434                        de->mtime = 0x1234;
     435                        de->mdate = 0x1234;
     436                } else if (idx == 1) {
     437                        /* Clear volume label entry */
     438                        memset(buffer, 0, cfg->sector_size);
    350439                }
    351         } else {
    352                 for (i = 0; i < cfg->sectors_per_cluster; i++) {
    353                         rc = block_write_direct(service_id, addr, 1, buffer);
    354                         if (rc != EOK)
    355                                 return EIO;
    356 
    357                         ++addr;
    358                 }       
     440
     441                rc = block_write_direct(service_id, addr, 1, buffer);
     442                if (rc != EOK)
     443                        return EIO;
     444
     445                ++addr;
    359446        }
    360447
     
    367454static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    368455{
     456        const char *bs_label;
     457
     458        /*
     459         * The boot sector must always contain a valid label. If there
     460         * is no label, there should be 'NO NAME'
     461         */
     462        if (cfg->label != NULL)
     463                bs_label = cfg->label;
     464        else
     465                bs_label = LABEL_NONAME;
    369466        memset(bs, 0, sizeof(*bs));
    370467
     
    405502                bs->fat32.root_cluster = 2;
    406503
    407                 memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     504                (void) fat_label_encode(&bs->fat32.label, bs_label);
    408505                memcpy(bs->fat32.type, "FAT32   ", 8);
    409506        } else {
     
    413510                bs->id = host2uint32_t_be(0x12345678);
    414511
    415                 memcpy(bs->label, "HELENOS_NEW", 11);
    416                 memcpy(bs->type, "FAT   ", 8);
     512                (void) fat_label_encode(&bs->label, bs_label);
     513                if (cfg->fat_type == FAT12)
     514                        memcpy(bs->type, "FAT12   ", 8);
     515                else
     516                        memcpy(bs->type, "FAT16   ", 8);
    417517        }
    418518}
Note: See TracChangeset for help on using the changeset viewer.