Ignore:
File:
1 edited

Legend:

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

    r51d0ee9 r991f645  
    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 <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 /** 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, service_id_t service_id);
    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    devmap_handle_t handle);
     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         service_id_t service_id;
     97        devmap_handle_t handle;
     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 = loc_service_get_id(dev_path, &service_id, 0);
     139
     140        rc = devmap_device_get_handle(dev_path, &handle, 0);
    159141        if (rc != EOK) {
    160142                printf(NAME ": Error resolving device `%s'.\n", dev_path);
     
    162144        }
    163145
    164         rc = block_init(EXCHANGE_SERIALIZE, service_id, 2048);
     146        rc = block_init(handle, 2048);
    165147        if (rc != EOK)  {
    166148                printf(NAME ": Error initializing libblock.\n");
     
    168150        }
    169151
    170         rc = block_get_bsize(service_id, &cfg.sector_size);
     152        rc = block_get_bsize(handle, &block_size);
    171153        if (rc != EOK) {
    172154                printf(NAME ": Error determining device block size.\n");
     
    174156        }
    175157
    176         rc = block_get_nblocks(service_id, &dev_nblocks);
     158        rc = block_get_nblocks(handle, &dev_nblocks);
    177159        if (rc != EOK) {
    178160                printf(NAME ": Warning, failed to obtain block device size.\n");
     
    180162                printf(NAME ": Block device has %" PRIuOFF64 " blocks.\n",
    181163                    dev_nblocks);
    182                 if (!cfg.total_sectors || dev_nblocks < cfg.total_sectors)
    183                         cfg.total_sectors = 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;
    184170        }
    185171
     
    189175        }
    190176
    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);
     177        printf(NAME ": Creating FAT filesystem on device %s.\n", dev_path);
     178
     179        rc = fat_params_compute(&cfg, &par);
    199180        if (rc != EOK) {
    200181                printf(NAME ": Invalid file-system parameters.\n");
     
    202183        }
    203184
    204         rc = fat_blocks_write(&cfg, service_id);
     185        rc = fat_blocks_write(&par, handle);
    205186        if (rc != EOK) {
    206187                printf(NAME ": Error writing device.\n");
     
    208189        }
    209190
    210         block_fini(service_id);
     191        block_fini(handle);
    211192        printf("Success.\n");
    212193
     
    216197static void syntax_print(void)
    217198{
    218         printf("syntax: mkfat [--size <sectors>] [--type 12|16|32] <device_name>\n");
     199        printf("syntax: mkfat [--size <num_blocks>] <device_name>\n");
    219200}
    220201
     
    224205 * file system params.
    225206 */
    226 static int fat_params_compute(struct fat_cfg *cfg)
     207static int fat_params_compute(struct fat_cfg const *cfg, struct fat_params *par)
    227208{
    228209        uint32_t fat_bytes;
     
    230211
    231212        /*
    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);
     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;
    258231
    259232        return EOK;
     
    261234
    262235/** Create file system with the given parameters. */
    263 static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id)
     236static int fat_blocks_write(struct fat_params const *par, devmap_handle_t handle)
    264237{
    265238        aoff64_t addr;
     
    270243        struct fat_bs bs;
    271244
    272         fat_bootsec_create(cfg, &bs);
    273 
    274         rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     245        fat_bootsec_create(par, &bs);
     246
     247        rc = block_write_direct(handle, BS_BLOCK, 1, &bs);
    275248        if (rc != EOK)
    276249                return EIO;
     
    278251        addr = BS_BLOCK + 1;
    279252
    280         buffer = calloc(cfg->sector_size, 1);
     253        buffer = calloc(sector_size, 1);
    281254        if (buffer == NULL)
    282255                return ENOMEM;
    283         memset(buffer, 0, cfg->sector_size);
    284256
    285257        /* Reserved sectors */
    286         for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    287                 rc = block_write_direct(service_id, addr, 1, buffer);
     258        for (i = 0; i < par->reserved_sectors - 1; ++i) {
     259                rc = block_write_direct(handle, addr, 1, buffer);
    288260                if (rc != EOK)
    289261                        return EIO;
     
    293265
    294266        /* File allocation tables */
    295         for (i = 0; i < cfg->fat_count; ++i) {
     267        for (i = 0; i < fat_count; ++i) {
    296268                printf("Writing allocation table %d.\n", i + 1);
    297269
    298                 for (j = 0; j < cfg->fat_sectors; ++j) {
    299                         memset(buffer, 0, cfg->sector_size);
     270                for (j = 0; j < par->fat_sectors; ++j) {
     271                        memset(buffer, 0, sector_size);
    300272                        if (j == 0) {
    301                                 buffer[0] = default_media_descriptor;
     273                                buffer[0] = media_descriptor;
    302274                                buffer[1] = 0xFF;
    303275                                buffer[2] = 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                                 }
     276                                buffer[3] = 0xFF;
    317277                        }
    318278
    319                         rc = block_write_direct(service_id, addr, 1, buffer);
     279                        rc = block_write_direct(handle, addr, 1, buffer);
    320280                        if (rc != EOK)
    321281                                return EIO;
     
    325285        }
    326286
     287        printf("Writing root directory.\n");
     288
     289        memset(buffer, 0, sector_size);
     290
    327291        /* Root directory */
    328         printf("Writing root directory.\n");
    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                 }       
     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;
    347298        }
    348299
     
    353304
    354305/** Construct boot sector with the given parameters. */
    355 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)
    356307{
    357308        memset(bs, 0, sizeof(*bs));
     
    364315
    365316        /* BIOS Parameter Block */
    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;
     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);
    381330        bs->sec_per_track = host2uint16_t_le(63);
    382         bs->signature = host2uint16_t_be(0x55AA);
    383331        bs->headcnt = host2uint16_t_le(6);
    384332        bs->hidden_sec = host2uint32_t_le(0);
    385333
    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         }
     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);
    406347}
    407348
Note: See TracChangeset for help on using the changeset viewer.