Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset dabe1664 in mainline


Ignore:
Timestamp:
2012-02-21T21:56:11Z (9 years ago)
Author:
Maurizio Lombardi <m.lombardi85@…>
Branches:
master
Children:
9587b37
Parents:
55dbaeb
Message:

mkexfat: Initialize the main extended boot sector and the checksum block

File:
1 edited

Legend:

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

    r55dbaeb rdabe1664  
    5656#define EBS_SECTOR_START 1
    5757
     58/** First sector of the Main Extended Boot Region Backup */
     59#define EBS_BACKUP_SECTOR_START 13
     60
     61/** First sector of the VBR */
     62#define VBR_SECTOR 0
     63
     64/** First sector if the VBR Backup */
     65#define VBR_BACKUP_SECTOR 12
     66
    5867/** Size of the Main Extended Boot Region */
    5968#define EBS_SIZE 8
     
    6473/** The default size of each cluster is 4096 byte */
    6574#define DEFAULT_CLUSTER_SIZE 4096
    66 
    67 static unsigned log2(unsigned n);
    6875
    6976typedef struct exfat_cfg {
     
    7885} exfat_cfg_t;
    7986
     87
     88static unsigned log2(unsigned n);
     89
     90static uint32_t
     91vbr_checksum_start(void const *octets, size_t nbytes);
     92
     93static void
     94vbr_checksum_update(void const *octets, size_t nbytes, uint32_t *checksum);
     95
     96static int
     97ebs_write(service_id_t service_id, exfat_cfg_t *cfg,
     98    int base, uint32_t *chksum);
     99
    80100static void usage(void)
    81101{
     
    143163 * @param vbr Pointer to the Volume Boot Record structure.
    144164 * @param cfg Pointer to the exFAT configuration structure.
    145  */
    146 static void
     165 * @return    Initial checksum value.
     166 */
     167static uint32_t
    147168vbr_initialize(exfat_bs_t *vbr, exfat_cfg_t *cfg)
    148169{
     
    182203        vbr->allocated_percent = 0;
    183204        vbr->signature = host2uint16_t_le(0xAA55);
     205
     206        return vbr_checksum_start(vbr, sizeof(exfat_bs_t));
     207}
     208
     209static int
     210bootsec_write(service_id_t service_id, exfat_cfg_t *cfg)
     211{
     212        exfat_bs_t vbr;
     213        uint32_t vbr_checksum;
     214        uint32_t initial_checksum;
     215        int rc;
     216
     217        vbr_checksum = vbr_initialize(&vbr, cfg);
     218        initial_checksum = vbr_checksum;
     219
     220        /* Write the VBR on disk */
     221        rc = block_write_direct(service_id, VBR_SECTOR, 1, &vbr);
     222        if (rc != EOK)
     223                return rc;
     224
     225        /* Write the VBR backup on disk */
     226        rc = block_write_direct(service_id, VBR_BACKUP_SECTOR, 1, &vbr);
     227        if (rc != EOK)
     228                return rc;
     229
     230        rc = ebs_write(service_id, cfg, EBS_SECTOR_START, &vbr_checksum);
     231        if (rc != EOK)
     232                return rc;
     233
     234        /* Restore the checksum to its initial value */
     235        vbr_checksum = initial_checksum;
     236
     237        return ebs_write(service_id, cfg, EBS_BACKUP_SECTOR_START, &vbr_checksum);
    184238}
    185239
     
    188242 * @param service_id  The service id.
    189243 * @param cfg  Pointer to the exFAT configuration structure.
     244 * @param base Base sector of the EBS.
    190245 * @return  EOK on success or a negative error code.
    191246 */
    192247static int
    193 ebs_write(service_id_t service_id, exfat_cfg_t *cfg)
     248ebs_write(service_id_t service_id, exfat_cfg_t *cfg, int base, uint32_t *chksum)
    194249{
    195250        uint32_t *ebs = calloc(cfg->sector_size, sizeof(uint8_t));
    196251        int i, rc;
     252        unsigned idx;
    197253
    198254        if (!ebs)
     
    202258
    203259        for (i = 0; i < EBS_SIZE; ++i) {
    204                 rc = block_write_direct(service_id, i + EBS_SECTOR_START,
    205                     1, ebs);
     260                vbr_checksum_update(ebs, cfg->sector_size, chksum);
     261
     262                rc = block_write_direct(service_id,
     263                    i + EBS_SECTOR_START + base, 1, ebs);
    206264
    207265                if (rc != EOK)
    208266                        goto exit;
    209267        }
     268
     269        /* The OEM record is not yet used
     270         * by the official exFAT implementation, we'll fill
     271         * it with zeroes.
     272         */
     273
     274        memset(ebs, 0, cfg->sector_size);
     275        vbr_checksum_update(ebs, cfg->sector_size, chksum);
     276
     277        rc = block_write_direct(service_id, i++ + base, 1, ebs);
     278        if (rc != EOK)
     279                goto exit;
     280
     281        /* The next sector is reserved, fill it with zeroes too */
     282        vbr_checksum_update(ebs, cfg->sector_size, chksum);
     283        rc = block_write_direct(service_id, i++ + base, 1, ebs);
     284        if (rc != EOK)
     285                goto exit;
     286
     287        /* Write the checksum sector */
     288        for (idx = 0; idx < cfg->sector_size / sizeof(uint32_t); ++idx)
     289                ebs[idx] = host2uint32_t_le(*chksum);
     290
     291        rc = block_write_direct(service_id, i + base, 1, ebs);
    210292
    211293exit:
     
    251333}
    252334
    253 /** Given a power-of-two number (n), returns the result of log2(n).
     335/** Given a number (n), returns the result of log2(n).
    254336 *
    255337 * It works only if n is a power of two.
     
    265347}
    266348
     349/** Initialize the VBR checksum calculation */
     350static uint32_t
     351vbr_checksum_start(void const *data, size_t nbytes)
     352{
     353        uint32_t checksum = 0;
     354        size_t index;
     355        uint8_t const *octets = (uint8_t *) data;
     356
     357        for (index = 0; index < nbytes; ++index) {
     358                if (index == 106 || index == 107 || index == 112) {
     359                        /* Skip volume_flags and allocated_percent fields */
     360                        continue;
     361                }
     362
     363                checksum = ((checksum << 31) | (checksum >> 1)) + octets[index];
     364        }
     365
     366        return checksum;
     367}
     368
     369/** Update the VBR checksum */
     370static void
     371vbr_checksum_update(void const *data, size_t nbytes, uint32_t *checksum)
     372{
     373        size_t index;
     374        uint8_t const *octets = (uint8_t *) data;
     375
     376        for (index = 0; index < nbytes; ++index)
     377                *checksum = ((*checksum << 31) | (*checksum >> 1)) + octets[index];
     378}
     379
    267380int main (int argc, char **argv)
    268381{
    269382        exfat_cfg_t cfg;
    270         exfat_bs_t  vbr;
    271383        char *dev_path;
    272384        service_id_t service_id;
     
    323435        cfg_params_initialize(&cfg);
    324436        cfg_print_info(&cfg);
    325         vbr_initialize(&vbr, &cfg);
    326 
    327         /* Write the VBR on disk */
    328         rc = block_write_direct(service_id, 0, 1, &vbr);
    329         if (rc != EOK) {
    330                 printf(NAME ": Error, failed to write the VBR on disk\n");
    331                 return 2;
    332         }
    333 
    334         /* Write the VBR backup on disk */
    335         rc = block_write_direct(service_id, 12, 1, &vbr);
    336         if (rc != EOK) {
    337                 printf(NAME ": Error, failed to write the VBR" \
    338                     " backup on disk\n");
    339                 return 2;
    340         }
    341 
    342         rc = ebs_write(service_id, &cfg);
    343         if (rc != EOK) {
    344                 printf(NAME ": Error, failed to write the Main Extended Boot" \
    345                     " Sector to disk\n");
     437
     438        rc = bootsec_write(service_id, &cfg);
     439        if (rc != EOK) {
     440                printf(NAME ": Error, failed to write the VBR to disk\n");
    346441                return 2;
    347442        }
Note: See TracChangeset for help on using the changeset viewer.