Ignore:
File:
1 edited

Legend:

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

    r7234617 r15f3c3f  
    3535 * @brief       Tool for creating new FAT file systems.
    3636 *
    37  * Currently we can create 12/16/32-bit FAT.
     37 * Currently we can only create 16-bit FAT.
    3838 */
    3939
     
    4242#include <libblock.h>
    4343#include <mem.h>
    44 #include <devmap.h>
     44#include <loc.h>
    4545#include <byteorder.h>
    4646#include <sys/types.h>
     
    5555#define div_round_up(a, b) (((a) + (b) - 1) / (b))
    5656
    57 /** Default file-system parameters */
     57/** Predefined file-system parameters */
    5858enum {
    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 */
     59        sector_size             = 512,
     60        sectors_per_cluster     = 8,
     61        fat_count               = 2,
     62        reserved_clusters       = 2,
     63        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;
    7068        uint32_t total_sectors;
    7169        uint16_t root_ent_max;
    72         uint32_t addt_res_sectors;
    73         uint8_t sectors_per_cluster;
    74 
     70        uint16_t addt_res_sectors;
     71} fat_cfg_t;
     72
     73/** Derived file-system parameters */
     74typedef struct fat_params {
     75        struct fat_cfg cfg;
    7576        uint16_t reserved_sectors;
    76         uint32_t rootdir_sectors;
     77        uint16_t rootdir_sectors;
    7778        uint32_t fat_sectors;
    78         uint32_t total_clusters;
    79         uint8_t fat_count;
    80 } fat_cfg_t;
     79        uint16_t total_clusters;
     80} fat_params_t;
    8181
    8282static void syntax_print(void);
    8383
    84 static int fat_params_compute(struct fat_cfg *cfg);
    85 static int fat_blocks_write(struct fat_cfg const *cfg, devmap_handle_t handle);
    86 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs);
     84static int fat_params_compute(struct fat_cfg const *cfg,
     85    struct fat_params *par);
     86static int fat_blocks_write(struct fat_params const *par,
     87    service_id_t service_id);
     88static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs);
    8789
    8890int main(int argc, char **argv)
    8991{
     92        struct fat_params par;
    9093        struct fat_cfg cfg;
    9194
    9295        int rc;
    9396        char *dev_path;
    94         devmap_handle_t handle;
     97        service_id_t service_id;
     98        size_t block_size;
    9599        char *endptr;
    96100        aoff64_t dev_nblocks;
    97101
    98         cfg.sector_size = default_sector_size;
    99         cfg.sectors_per_cluster = default_sectors_per_cluster;
    100         cfg.fat_count = default_fat_count;
    101102        cfg.total_sectors = 0;
    102103        cfg.addt_res_sectors = 0;
    103104        cfg.root_ent_max = 128;
    104         cfg.fat_type = FAT16;
    105105
    106106        if (argc < 2) {
     
    111111
    112112        --argc; ++argv;
     113
    113114        if (str_cmp(*argv, "--size") == 0) {
    114115                --argc; ++argv;
     
    129130        }
    130131
    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 
    149132        if (argc != 1) {
    150133                printf(NAME ": Error, unexpected argument.\n");
     
    154137
    155138        dev_path = *argv;
    156         printf("Device: %s\n", dev_path);
    157 
    158         rc = devmap_device_get_handle(dev_path, &handle, 0);
     139
     140        rc = loc_service_get_id(dev_path, &service_id, 0);
    159141        if (rc != EOK) {
    160142                printf(NAME ": Error resolving device `%s'.\n", dev_path);
     
    162144        }
    163145
    164         rc = block_init(EXCHANGE_SERIALIZE, handle, 2048);
     146        rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
    165147        if (rc != EOK)  {
    166148                printf(NAME ": Error initializing libblock.\n");
     
    168150        }
    169151
    170         rc = block_get_bsize(handle, &cfg.sector_size);
     152        rc = block_get_bsize(service_id, &block_size);
    171153        if (rc != EOK) {
    172154                printf(NAME ": Error determining device block size.\n");
     
    174156        }
    175157
    176         rc = block_get_nblocks(handle, &dev_nblocks);
     158        rc = block_get_nblocks(service_id, &dev_nblocks);
    177159        if (rc != EOK) {
    178160                printf(NAME ": Warning, failed to obtain block device size.\n");
     
    183165        }
    184166
    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");
     167        if (block_size != 512) {
     168                printf(NAME ": Error. Device block size is not 512 bytes.\n");
    187169                return 2;
    188170        }
     
    193175        }
    194176
    195         printf(NAME ": Creating FAT%d filesystem on device %s.\n", cfg.fat_type, dev_path);
    196 
    197         rc = fat_params_compute(&cfg);
     177        printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
     178
     179        rc = fat_params_compute(&cfg, &par);
    198180        if (rc != EOK) {
    199181                printf(NAME ": Invalid file-system parameters.\n");
     
    201183        }
    202184
    203         rc = fat_blocks_write(&cfg, handle);
     185        rc = fat_blocks_write(&par, service_id);
    204186        if (rc != EOK) {
    205187                printf(NAME ": Error writing device.\n");
     
    207189        }
    208190
    209         block_fini(handle);
     191        block_fini(service_id);
    210192        printf("Success.\n");
    211193
     
    215197static void syntax_print(void)
    216198{
    217         printf("syntax: mkfat32 [--size <sectors>] [--type 12|16|32] <device_name>\n");
     199        printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
    218200}
    219201
     
    223205 * file system params.
    224206 */
    225 static int fat_params_compute(struct fat_cfg *cfg)
     207static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
    226208{
    227209        uint32_t fat_bytes;
     
    229211
    230212        /*
    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);
     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;
    260231
    261232        return EOK;
     
    263234
    264235/** Create file system with the given parameters. */
    265 static int fat_blocks_write(struct fat_cfg const *cfg, devmap_handle_t handle)
     236static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
    266237{
    267238        aoff64_t addr;
     
    272243        struct fat_bs bs;
    273244
    274         fat_bootsec_create(cfg, &bs);
    275 
    276         rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
     245        fat_bootsec_create(par, &bs);
     246
     247        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
    277248        if (rc != EOK)
    278249                return EIO;
     
    280251        addr = BS_BLOCK + 1;
    281252
    282         buffer = calloc(cfg->sector_size, 1);
     253        buffer = calloc(sector_size, 1);
    283254        if (buffer == NULL)
    284255                return ENOMEM;
    285         memset(buffer, 0, cfg->sector_size);
    286256
    287257        /* Reserved sectors */
    288         for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    289                 rc = block_write_direct(handle, addr, 1, buffer);
     258        for (i = 0; i < par->reserved_sectors - 1; ++i) {
     259                rc = block_write_direct(service_id, addr, 1, buffer);
    290260                if (rc != EOK)
    291261                        return EIO;
     
    295265
    296266        /* File allocation tables */
    297         for (i = 0; i < cfg->fat_count; ++i) {
     267        for (i = 0; i < fat_count; ++i) {
    298268                printf("Writing allocation table %d.\n", i + 1);
    299269
    300                 for (j = 0; j < cfg->fat_sectors; ++j) {
    301                         memset(buffer, 0, cfg->sector_size);
     270                for (j = 0; j < par->fat_sectors; ++j) {
     271                        memset(buffer, 0, sector_size);
    302272                        if (j == 0) {
    303                                 buffer[0] = default_media_descriptor;
     273                                buffer[0] = media_descriptor;
    304274                                buffer[1] = 0xFF;
    305275                                buffer[2] = 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                                 }
     276                                buffer[3] = 0xFF;
    319277                        }
    320278
    321                         rc = block_write_direct(handle, addr, 1, buffer);
     279                        rc = block_write_direct(service_id, addr, 1, buffer);
    322280                        if (rc != EOK)
    323281                                return EIO;
     
    327285        }
    328286
     287        printf("Writing root directory.\n");
     288
     289        memset(buffer, 0, sector_size);
     290
    329291        /* Root directory */
    330         printf("Writing root directory.\n");
    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                 }       
     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;
    349298        }
    350299
     
    355304
    356305/** Construct boot sector with the given parameters. */
    357 static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
     306static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
    358307{
    359308        memset(bs, 0, sizeof(*bs));
     
    366315
    367316        /* BIOS Parameter Block */
    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;
     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);
    383330        bs->sec_per_track = host2uint16_t_le(63);
    384         bs->signature = host2uint16_t_be(0x55AA);
    385331        bs->headcnt = host2uint16_t_le(6);
    386332        bs->hidden_sec = host2uint32_t_le(0);
    387333
    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         }
     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);
    408347}
    409348
Note: See TracChangeset for help on using the changeset viewer.