Changeset bf7ddde in mainline


Ignore:
Timestamp:
2015-07-08T17:19:26Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
70815a24
Parents:
603c1d1f
Message:

Generate and verify CRCs.

Location:
uspace/lib/label
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/label/include/types/liblabel.h

    r603c1d1f rbf7ddde  
    112112typedef struct {
    113113        uint64_t hdr_ba[2];
     114        uint32_t hdr_size;
    114115        uint64_t ptable_ba[2];
     116        uint64_t pt_blocks;
    115117        size_t esize;
     118        uint32_t pt_crc;
    116119} label_gpt_t;
    117120
  • uspace/lib/label/src/gpt.c

    r603c1d1f rbf7ddde  
    3434 */
    3535
     36#include <adt/checksum.h>
    3637#include <block.h>
    3738#include <byteorder.h>
     
    5859static int gpt_pte_to_part(label_t *, gpt_entry_t *, int);
    5960static int gpt_pte_update(label_t *, gpt_entry_t *, int);
     61
     62static int gpt_update_pt_crc(label_t *, uint32_t);
     63static void gpt_hdr_compute_crc(gpt_header_t *, size_t);
     64static int gpt_hdr_get_crc(gpt_header_t *, size_t, uint32_t *);
    6065
    6166const uint8_t efi_signature[8] = {
     
    8287        gpt_header_t *gpt_hdr[2];
    8388        gpt_entry_t *eptr;
    84         uint8_t *etable = NULL;
     89        uint8_t *etable[2];
    8590        size_t bsize;
    8691        uint32_t num_entries;
    8792        uint32_t esize;
    88         uint32_t bcnt;
     93        uint32_t pt_blocks;
    8994        uint64_t ptba[2];
    9095        uint64_t h1ba;
    9196        uint32_t entry;
     97        uint32_t pt_crc;
    9298        uint64_t ba_min, ba_max;
     99        uint32_t hdr_size;
     100        uint32_t hdr_crc;
    93101        int i, j;
    94102        int rc;
     
    96104        gpt_hdr[0] = NULL;
    97105        gpt_hdr[1] = NULL;
     106        etable[0] = NULL;
     107        etable[1] = NULL;
    98108
    99109        rc = block_get_bsize(sid, &bsize);
     
    149159        }
    150160
     161        if (uint32_t_le2host(gpt_hdr[0]->revision) !=
     162            uint32_t_le2host(gpt_hdr[1]->revision)) {
     163                rc = EINVAL;
     164                goto error;
     165        }
     166
     167        if (uint32_t_le2host(gpt_hdr[0]->header_size) !=
     168            uint32_t_le2host(gpt_hdr[1]->header_size)) {
     169                rc = EINVAL;
     170                goto error;
     171        }
     172
     173        hdr_size = uint32_t_le2host(gpt_hdr[0]->header_size);
     174        if (hdr_size < sizeof(gpt_header_t) ||
     175            hdr_size > bsize) {
     176                rc = EINVAL;
     177                goto error;
     178        }
     179
     180        for (j = 0; j < 2; j++) {
     181                rc = gpt_hdr_get_crc(gpt_hdr[j], hdr_size, &hdr_crc);
     182                if (rc != EOK)
     183                        goto error;
     184
     185                if (uint32_t_le2host(gpt_hdr[j]->header_crc32) != hdr_crc) {
     186                        rc = EINVAL;
     187                        goto error;
     188                }
     189        }
     190
     191        if (uint64_t_le2host(gpt_hdr[0]->my_lba) != gpt_hdr_ba) {
     192                rc = EINVAL;
     193                goto error;
     194        }
     195
     196        if (uint64_t_le2host(gpt_hdr[1]->my_lba) != h1ba) {
     197                rc = EINVAL;
     198                goto error;
     199        }
     200
     201        if (uint64_t_le2host(gpt_hdr[1]->alternate_lba) != gpt_hdr_ba) {
     202                rc = EINVAL;
     203                goto error;
     204        }
     205
    151206        num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries);
    152207        esize = uint32_t_le2host(gpt_hdr[0]->entry_size);
    153         bcnt = (num_entries + esize - 1) / esize;
     208        pt_blocks = (num_entries * esize + bsize - 1) / bsize;
    154209        ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba);
    155210        ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba);
    156211        ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba);
    157212        ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba);
     213        pt_crc = uint32_t_le2host(gpt_hdr[0]->pe_array_crc32);
     214
     215        if (uint64_t_le2host(gpt_hdr[1]->first_usable_lba) != ba_min) {
     216                rc = EINVAL;
     217                goto error;
     218        }
     219
     220        if (uint64_t_le2host(gpt_hdr[1]->last_usable_lba) != ba_max) {
     221                rc = EINVAL;
     222                goto error;
     223        }
     224
     225        for (i = 0; i < 16; i++) {
     226                if (gpt_hdr[1]->disk_guid[i] != gpt_hdr[0]->disk_guid[i]) {
     227                        rc = EINVAL;
     228                        goto error;
     229                }
     230        }
     231
     232        if (uint32_t_le2host(gpt_hdr[1]->num_entries) != num_entries) {
     233                rc = EINVAL;
     234                goto error;
     235        }
     236
     237        if (uint32_t_le2host(gpt_hdr[1]->entry_size) != esize) {
     238                rc = EINVAL;
     239                goto error;
     240        }
    158241
    159242        if (num_entries < 1) {
     
    172255        }
    173256
    174         etable = calloc(num_entries, esize);
    175         if (etable == NULL) {
    176                 rc = ENOMEM;
    177                 goto error;
    178         }
    179 
    180         rc = block_read_direct(sid, ptba[0], bcnt, etable);
    181         if (rc != EOK) {
    182                 rc = EIO;
    183                 goto error;
    184         }
    185 
    186         for (entry = 0; entry < num_entries; entry++) {
    187                 eptr = (gpt_entry_t *)(etable + entry * esize);
    188                 rc = gpt_pte_to_part(label, eptr, entry + 1);
    189                 if (rc != EOK)
    190                         goto error;
    191         }
    192 
    193         free(etable);
    194         etable = NULL;
     257        /* Check fields in backup header for validity */
     258
     259        for (j = 0; j < 2; j++) {
     260                etable[j] = calloc(1, pt_blocks * bsize);
     261                if (etable[j] == NULL) {
     262                        rc = ENOMEM;
     263                        goto error;
     264                }
     265
     266                rc = block_read_direct(sid, ptba[j], pt_blocks / 2, etable[j]);
     267                if (rc != EOK) {
     268                        rc = EIO;
     269                        goto error;
     270                }
     271
     272                if (compute_crc32(etable[j], num_entries * esize) != pt_crc) {
     273                        rc = EIO;
     274                        goto error;
     275                }
     276
     277                for (entry = 0; entry < num_entries; entry++) {
     278                        eptr = (gpt_entry_t *)(etable[j] + entry * esize);
     279                        rc = gpt_pte_to_part(label, eptr, entry + 1);
     280                        if (rc != EOK)
     281                                goto error;
     282                }
     283        }
     284
     285        free(etable[0]);
     286        etable[0] = NULL;
     287        free(etable[1]);
     288        etable[1] = NULL;
    195289        free(gpt_hdr[0]);
    196290        gpt_hdr[0] = NULL;
     
    211305        label->lt.gpt.ptable_ba[1] = ptba[1];
    212306        label->lt.gpt.esize = esize;
     307        label->lt.gpt.pt_blocks = pt_blocks;
     308        label->lt.gpt.pt_crc = pt_crc;
     309        label->lt.gpt.hdr_size = hdr_size;
    213310
    214311        *rlabel = label;
    215312        return EOK;
    216313error:
    217         free(etable);
     314        free(etable[0]);
     315        free(etable[1]);
    218316        free(gpt_hdr[0]);
    219317        free(gpt_hdr[1]);
     
    236334        aoff64_t nblocks;
    237335        uint64_t resv_blocks;
     336        uint32_t pt_crc;
    238337        int i, j;
    239338        int rc;
     
    277376
    278377        for (i = 0; i < 2; i++) {
     378                etable = calloc(1, pt_blocks * bsize);
     379                if (etable == NULL) {
     380                        rc = ENOMEM;
     381                        goto error;
     382                }
     383
     384                rc = block_write_direct(sid, ptba[i], pt_blocks, etable);
     385                if (rc != EOK) {
     386                        rc = EIO;
     387                        goto error;
     388                }
     389
     390                pt_crc = compute_crc32((uint8_t *)etable,
     391                    num_entries * esize);
     392
     393                free(etable);
     394                etable = NULL;
     395
    279396                gpt_hdr = calloc(1, bsize);
    280397                if (gpt_hdr == NULL) {
     
    287404                gpt_hdr->revision = host2uint32_t_le(gpt_revision);
    288405                gpt_hdr->header_size = host2uint32_t_le(sizeof(gpt_header_t));
    289                 gpt_hdr->header_crc32 = 0; /* XXX */
     406                gpt_hdr->header_crc32 = 0;
    290407                gpt_hdr->my_lba = host2uint64_t_le(hdr_ba[i]);
    291408                gpt_hdr->alternate_lba = host2uint64_t_le(hdr_ba[1 - i]);
    292409                gpt_hdr->first_usable_lba = host2uint64_t_le(ba_min);
    293410                gpt_hdr->last_usable_lba = host2uint64_t_le(ba_max);
    294                 //gpt_hdr->disk_guid
     411                //gpt_hdr->disk_guid XXX
    295412                gpt_hdr->entry_lba = host2uint64_t_le(ptba[i]);
    296413                gpt_hdr->num_entries = host2uint32_t_le(num_entries);
    297414                gpt_hdr->entry_size = host2uint32_t_le(esize);
    298                 gpt_hdr->pe_array_crc32 = 0; /* XXXX */
     415                gpt_hdr->pe_array_crc32 = pt_crc;
     416
     417                gpt_hdr_compute_crc(gpt_hdr, sizeof(gpt_header_t));
    299418
    300419                rc = block_write_direct(sid, hdr_ba[i], 1, gpt_hdr);
     
    306425                free(gpt_hdr);
    307426                gpt_hdr = NULL;
    308 
    309                 etable = calloc(num_entries, esize);
    310                 if (etable == NULL) {
    311                         rc = ENOMEM;
    312                         goto error;
    313                 }
    314 
    315                 rc = block_write_direct(sid, ptba[i], pt_blocks, etable);
    316                 if (rc != EOK) {
    317                         rc = EIO;
    318                         goto error;
    319                 }
    320 
    321                 free(etable);
    322                 etable = 0;
    323427        }
    324428
     
    342446        label->lt.gpt.ptable_ba[1] = ptba[1];
    343447        label->lt.gpt.esize = esize;
     448        label->lt.gpt.pt_blocks = pt_blocks;
     449        label->lt.gpt.hdr_size = sizeof(gpt_header_t);
    344450
    345451        *rlabel = label;
     
    371477        uint8_t *etable = NULL;
    372478        label_part_t *part;
    373         uint64_t pt_blocks;
    374479        int i;
    375480        int rc;
     
    380485                goto error;
    381486        }
    382 
    383         pt_blocks = label->pri_entries * label->lt.gpt.esize /
    384             label->block_size;
    385487
    386488        for (i = 0; i < 2; i++) {
     
    401503                gpt_hdr = NULL;
    402504
    403                 etable = calloc(label->pri_entries, label->lt.gpt.esize);
     505                etable = calloc(1, label->lt.gpt.pt_blocks *
     506                    label->block_size);
    404507                if (etable == NULL) {
    405508                        rc = ENOMEM;
     
    408511
    409512                rc = block_write_direct(label->svc_id,
    410                     label->lt.gpt.ptable_ba[i], pt_blocks, etable);
     513                    label->lt.gpt.ptable_ba[i], label->lt.gpt.pt_blocks,
     514                    etable);
    411515                if (rc != EOK) {
    412516                        rc = EIO;
     
    596700{
    597701        size_t pos;
    598         size_t offs;
    599702        uint64_t ba;
     703        uint64_t nblocks;
     704        size_t ptbytes;
    600705        uint8_t *buf;
    601706        gpt_entry_t *e;
     707        uint32_t crc;
    602708        int i;
    603709        int rc;
    604710
     711        /* Byte offset of partition entry */
    605712        pos = index * label->lt.gpt.esize;
    606         offs = pos % label->block_size;
    607 
    608         buf = calloc(1, label->block_size);
     713        /* Number of bytes in partition table */
     714        ptbytes = label->pri_entries * label->lt.gpt.esize;
     715
     716        buf = calloc(1, label->block_size * label->lt.gpt.pt_blocks);
    609717        if (buf == NULL)
    610718                return ENOMEM;
     
    612720        /* For both partition tables: read, modify, write */
    613721        for (i = 0; i < 2; i++) {
    614                 ba = label->lt.gpt.ptable_ba[i] +
    615                     pos / label->block_size;
    616 
    617                 rc = block_read_direct(label->svc_id, ba, 1, buf);
    618                 if (rc != EOK) {
     722                ba = label->lt.gpt.ptable_ba[i];
     723                nblocks = label->lt.gpt.pt_blocks;
     724
     725                rc = block_read_direct(label->svc_id, ba, nblocks, buf);
     726                if (rc != EOK) {
     727                        rc = EIO;
     728                        goto error;
     729                }
     730
     731                crc = compute_crc32(buf, ptbytes);
     732                if (crc != label->lt.gpt.pt_crc) {
     733                        /* Corruption detected */
    619734                        rc = EIO;
    620735                        goto error;
     
    622737
    623738                /* Replace single entry */
    624                 e = (gpt_entry_t *)(&buf[offs]);
     739                e = (gpt_entry_t *)(&buf[pos]);
    625740                *e = *pte;
    626741
    627                 rc = block_write_direct(label->svc_id, ba, 1, buf);
     742                rc = block_write_direct(label->svc_id, ba, nblocks, buf);
     743                if (rc != EOK) {
     744                        rc = EIO;
     745                        goto error;
     746                }
     747
     748                crc = compute_crc32(buf, ptbytes);
     749                rc = gpt_update_pt_crc(label, crc);
    628750                if (rc != EOK) {
    629751                        rc = EIO;
     
    639761}
    640762
     763static int gpt_update_pt_crc(label_t *label, uint32_t crc)
     764{
     765        gpt_header_t *gpt_hdr;
     766        int rc;
     767        int i;
     768
     769        gpt_hdr = calloc(1, label->block_size);
     770        if (gpt_hdr == NULL) {
     771                rc = ENOMEM;
     772                goto error;
     773        }
     774
     775        for (i = 0; i < 2; i++) {
     776                rc = block_read_direct(label->svc_id,
     777                    label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
     778                if (rc != EOK) {
     779                        rc = EIO;
     780                        goto error;
     781                }
     782
     783                gpt_hdr->pe_array_crc32 = host2uint32_t_le(crc);
     784                gpt_hdr_compute_crc(gpt_hdr, label->lt.gpt.hdr_size);
     785
     786                rc = block_write_direct(label->svc_id,
     787                    label->lt.gpt.hdr_ba[i], 1, gpt_hdr);
     788                if (rc != EOK) {
     789                        rc = EIO;
     790                        goto error;
     791                }
     792        }
     793
     794        free(gpt_hdr);
     795        return EOK;
     796error:
     797        return rc;
     798}
     799
     800static void gpt_hdr_compute_crc(gpt_header_t *hdr, size_t hdr_size)
     801{
     802        uint32_t crc;
     803
     804        hdr->header_crc32 = 0;
     805        crc = compute_crc32((uint8_t *)hdr, hdr_size);
     806        hdr->header_crc32 = crc;
     807}
     808
     809static int gpt_hdr_get_crc(gpt_header_t *hdr, size_t hdr_size, uint32_t *crc)
     810{
     811        gpt_header_t *c;
     812
     813        c = calloc(1, sizeof(gpt_header_t));
     814        if (c == NULL)
     815                return ENOMEM;
     816
     817        memcpy(c, hdr, hdr_size);
     818        c->header_crc32 = 0;
     819        *crc = compute_crc32((uint8_t *)c, hdr_size);
     820        free(c);
     821
     822        return EOK;
     823}
     824
    641825/** @}
    642826 */
Note: See TracChangeset for help on using the changeset viewer.