Changeset 4cf5ed46 in mainline for uspace/app/mkfat/mkfat.c


Ignore:
Timestamp:
2011-08-26T23:52:15Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
51d0ee9
Parents:
7fadb65 (diff), 0be611b (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 from lp:~jakub/helenos/fat-from-oleg.

  • This merge effectively merges Oleg Romanenko's GSoC 2011 changes.
  • Support for FAT12, FAT32.
  • Support for LFN.
  • Initial read/write support for exFAT.
File:
1 edited

Legend:

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

    r7fadb65 r4cf5ed46  
    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 = (cfg->total_clusters + 2) * FAT_SIZE(cfg->fat_type);
     256        cfg->fat_sectors = div_round_up(fat_bytes, cfg->sector_size);
    231257
    232258        return EOK;
     
    234260
    235261/** Create file system with the given parameters. */
    236 static int fat_blocks_write(struct fat_params const *par, service_id_t service_id)
     262static int fat_blocks_write(struct fat_cfg const *cfg, service_id_t service_id)
    237263{
    238264        aoff64_t addr;
     
    243269        struct fat_bs bs;
    244270
    245         fat_bootsec_create(par, &bs);
     271        fat_bootsec_create(cfg, &bs);
    246272
    247273        rc = block_write_direct(service_id, BS_BLOCK, 1, &bs);
     
    251277        addr = BS_BLOCK + 1;
    252278
    253         buffer = calloc(sector_size, 1);
     279        buffer = calloc(cfg->sector_size, 1);
    254280        if (buffer == NULL)
    255281                return ENOMEM;
     282        memset(buffer, 0, cfg->sector_size);
    256283
    257284        /* Reserved sectors */
    258         for (i = 0; i < par->reserved_sectors - 1; ++i) {
     285        for (i = 0; i < cfg->reserved_sectors - 1; ++i) {
    259286                rc = block_write_direct(service_id, addr, 1, buffer);
    260287                if (rc != EOK)
     
    265292
    266293        /* File allocation tables */
    267         for (i = 0; i < fat_count; ++i) {
     294        for (i = 0; i < cfg->fat_count; ++i) {
    268295                printf("Writing allocation table %d.\n", i + 1);
    269296
    270                 for (j = 0; j < par->fat_sectors; ++j) {
    271                         memset(buffer, 0, sector_size);
     297                for (j = 0; j < cfg->fat_sectors; ++j) {
     298                        memset(buffer, 0, cfg->sector_size);
    272299                        if (j == 0) {
    273                                 buffer[0] = media_descriptor;
     300                                buffer[0] = default_media_descriptor;
    274301                                buffer[1] = 0xFF;
    275302                                buffer[2] = 0xFF;
    276                                 buffer[3] = 0xFF;
     303                                if (cfg->fat_type == FAT16) {
     304                                        buffer[3] = 0xFF;
     305                                } else if (cfg->fat_type == FAT32) {
     306                                        buffer[3] = 0x0F;
     307                                        buffer[4] = 0xFF;
     308                                        buffer[5] = 0xFF;
     309                                        buffer[6] = 0xFF;
     310                                        buffer[7] = 0x0F;
     311                                        buffer[8] = 0xF8;
     312                                        buffer[9] = 0xFF;
     313                                        buffer[10] = 0xFF;
     314                                        buffer[11] = 0x0F;
     315                                }
    277316                        }
    278317
     
    285324        }
    286325
     326        /* Root directory */
    287327        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;
     328        memset(buffer, 0, cfg->sector_size);
     329        if (cfg->fat_type != FAT32) {
     330                size_t idx;
     331                for (idx = 0; idx < cfg->rootdir_sectors; ++idx) {
     332                        rc = block_write_direct(service_id, addr, 1, buffer);
     333                        if (rc != EOK)
     334                                return EIO;
     335
     336                        ++addr;
     337                }
     338        } else {
     339                for (i = 0; i < cfg->sectors_per_cluster; i++) {
     340                        rc = block_write_direct(service_id, addr, 1, buffer);
     341                        if (rc != EOK)
     342                                return EIO;
     343
     344                        ++addr;
     345                }       
    298346        }
    299347
     
    304352
    305353/** Construct boot sector with the given parameters. */
    306 static void fat_bootsec_create(struct fat_params const *par, struct fat_bs *bs)
     354static void fat_bootsec_create(struct fat_cfg const *cfg, struct fat_bs *bs)
    307355{
    308356        memset(bs, 0, sizeof(*bs));
     
    315363
    316364        /* 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);
     365        bs->bps = host2uint16_t_le(cfg->sector_size);
     366        bs->spc = cfg->sectors_per_cluster;
     367        bs->rscnt = host2uint16_t_le(cfg->reserved_sectors);
     368        bs->fatcnt = cfg->fat_count;
     369        bs->root_ent_max = host2uint16_t_le(cfg->root_ent_max);
     370
     371        if (cfg->total_sectors < 0x10000) {
     372                bs->totsec16 = host2uint16_t_le(cfg->total_sectors);
     373                bs->totsec32 = 0;
     374        } else {
     375                bs->totsec16 = 0;
     376                bs->totsec32 = host2uint32_t_le(cfg->total_sectors);
     377        }
     378
     379        bs->mdesc = default_media_descriptor;
    330380        bs->sec_per_track = host2uint16_t_le(63);
     381        bs->signature = host2uint16_t_be(0x55AA);
    331382        bs->headcnt = host2uint16_t_le(6);
    332383        bs->hidden_sec = host2uint32_t_le(0);
    333384
    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);
     385        if (cfg->fat_type == FAT32) {
     386                bs->sec_per_fat = 0;
     387                bs->fat32.sectors_per_fat = host2uint32_t_le(cfg->fat_sectors);
     388
     389                bs->fat32.pdn = 0x80;
     390                bs->fat32.ebs = 0x29;
     391                bs->fat32.id = host2uint32_t_be(0x12345678);
     392                bs->fat32.root_cluster = 2;
     393
     394                memcpy(bs->fat32.label, "HELENOS_NEW", 11);
     395                memcpy(bs->fat32.type, "FAT32   ", 8);
     396        } else {
     397                bs->sec_per_fat = host2uint16_t_le(cfg->fat_sectors);
     398                bs->pdn = 0x80;
     399                bs->ebs = 0x29;
     400                bs->id = host2uint32_t_be(0x12345678);
     401
     402                memcpy(bs->label, "HELENOS_NEW", 11);
     403                memcpy(bs->type, "FAT   ", 8);
     404        }
    347405}
    348406
Note: See TracChangeset for help on using the changeset viewer.