Changeset 99c23405 in mainline for uspace/lib/label/src/gpt.c


Ignore:
Timestamp:
2015-07-04T15:18:06Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
603c1d1f
Parents:
6bc542b
Message:

Persistent partition table modification when creating or deleting partition.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/label/src/gpt.c

    r6bc542b r99c23405  
    5454static int gpt_part_destroy(label_part_t *);
    5555
     56static void gpt_unused_pte(gpt_entry_t *);
     57static int gpt_part_to_pte(label_part_t *, gpt_entry_t *);
    5658static int gpt_pte_to_part(label_t *, gpt_entry_t *, int);
     59static int gpt_pte_update(label_t *, gpt_entry_t *, int);
    5760
    5861const uint8_t efi_signature[8] = {
     
    7780{
    7881        label_t *label = NULL;
    79         gpt_header_t *gpt_hdr = NULL;
     82        gpt_header_t *gpt_hdr[2];
    8083        gpt_entry_t *eptr;
    8184        uint8_t *etable = NULL;
     
    8487        uint32_t esize;
    8588        uint32_t bcnt;
    86         uint64_t ba;
     89        uint64_t ptba[2];
     90        uint64_t h1ba;
    8791        uint32_t entry;
    8892        uint64_t ba_min, ba_max;
    89         int i;
     93        int i, j;
    9094        int rc;
    9195
     96        gpt_hdr[0] = NULL;
     97        gpt_hdr[1] = NULL;
     98
    9299        rc = block_get_bsize(sid, &bsize);
    93100        if (rc != EOK) {
     
    101108        }
    102109
    103         gpt_hdr = calloc(1, bsize);
    104         if (gpt_hdr == NULL) {
     110        gpt_hdr[0] = calloc(1, bsize);
     111        if (gpt_hdr[0] == NULL) {
    105112                rc = ENOMEM;
    106113                goto error;
    107114        }
    108115
    109         rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr);
     116        gpt_hdr[1] = calloc(1, bsize);
     117        if (gpt_hdr[1] == NULL) {
     118                rc = ENOMEM;
     119                goto error;
     120        }
     121
     122        rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr[0]);
     123        if (rc != EOK) {
     124                rc = EIO;
     125                goto error;
     126        }
     127
     128        h1ba = uint64_t_le2host(gpt_hdr[0]->alternate_lba);
     129
     130        rc = block_read_direct(sid, h1ba, 1, gpt_hdr[1]);
    110131        if (rc != EOK) {
    111132                rc = EIO;
     
    119140        list_initialize(&label->parts);
    120141
    121         for (i = 0; i < 8; ++i) {
    122                 if (gpt_hdr->efi_signature[i] != efi_signature[i]) {
    123                         rc = EINVAL;
    124                         goto error;
     142        for (j = 0; j < 2; j++) {
     143                for (i = 0; i < 8; ++i) {
     144                        if (gpt_hdr[j]->efi_signature[i] != efi_signature[i]) {
     145                                rc = EINVAL;
     146                                goto error;
     147                        }
    125148                }
    126149        }
    127150
    128         num_entries = uint32_t_le2host(gpt_hdr->num_entries);
    129         esize = uint32_t_le2host(gpt_hdr->entry_size);
     151        num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries);
     152        esize = uint32_t_le2host(gpt_hdr[0]->entry_size);
    130153        bcnt = (num_entries + esize - 1) / esize;
    131         ba = uint64_t_le2host(gpt_hdr->entry_lba);
    132         ba_min = uint64_t_le2host(gpt_hdr->first_usable_lba);
    133         ba_max = uint64_t_le2host(gpt_hdr->last_usable_lba);
     154        ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba);
     155        ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba);
     156        ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba);
     157        ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba);
    134158
    135159        if (num_entries < 1) {
     
    154178        }
    155179
    156         rc = block_read_direct(sid, ba, bcnt, etable);
     180        rc = block_read_direct(sid, ptba[0], bcnt, etable);
    157181        if (rc != EOK) {
    158182                rc = EIO;
     
    169193        free(etable);
    170194        etable = NULL;
    171         free(gpt_hdr);
    172         gpt_hdr = NULL;
     195        free(gpt_hdr[0]);
     196        gpt_hdr[0] = NULL;
     197        free(gpt_hdr[1]);
     198        gpt_hdr[1] = NULL;
    173199
    174200        label->ops = &gpt_label_ops;
    175201        label->ltype = lt_gpt;
     202        label->svcid = sid;
    176203        label->ablock0 = ba_min;
    177204        label->anblocks = ba_max - ba_min + 1;
     205        label->pri_entries = num_entries;
     206        label->block_size = bsize;
     207
     208        label->lt.gpt.ptable_ba[0] = ptba[0];
     209        label->lt.gpt.ptable_ba[1] = ptba[1];
     210        label->lt.gpt.esize = esize;
     211
    178212        *rlabel = label;
    179213        return EOK;
    180214error:
    181215        free(etable);
    182         free(gpt_hdr);
     216        free(gpt_hdr[0]);
     217        free(gpt_hdr[1]);
    183218        free(label);
    184219        return rc;
     
    243278{
    244279        label_part_t *part;
     280        gpt_entry_t pte;
     281        int rc;
    245282
    246283        part = calloc(1, sizeof(label_part_t));
    247         if (part == NULL)
    248                 return ENOMEM;
     284        if (part == NULL) {
     285                rc = ENOMEM;
     286                goto error;
     287        }
    249288
    250289        /* XXX Verify index, block0, nblocks */
    251290
     291        if (pspec->index < 1 || pspec->index > label->pri_entries) {
     292                rc = EINVAL;
     293                goto error;
     294        }
     295
     296        /* XXX Check if index is used */
     297
     298        part->label = label;
    252299        part->index = pspec->index;
    253300        part->block0 = pspec->block0;
    254301        part->nblocks = pspec->nblocks;
    255 
    256         /* XXX Modify partition table */
    257 
    258         part->label = label;
     302        part->ptype = pspec->ptype;
     303
     304        /* Prepare partition table entry */
     305        rc = gpt_part_to_pte(part, &pte);
     306        if (rc != EOK) {
     307                rc = EINVAL;
     308                goto error;
     309        }
     310
     311        /* Modify partition tables */
     312        rc = gpt_pte_update(label, &pte, pspec->index - 1);
     313        if (rc != EOK) {
     314                rc = EIO;
     315                goto error;
     316        }
     317
    259318        list_append(&part->llabel, &label->parts);
    260319
    261320        *rpart = part;
    262321        return EOK;
     322error:
     323        free(part);
     324        return rc;
    263325}
    264326
    265327static int gpt_part_destroy(label_part_t *part)
    266328{
    267         return ENOTSUP;
     329        gpt_entry_t pte;
     330        int rc;
     331
     332        /* Prepare unused partition table entry */
     333        gpt_unused_pte(&pte);
     334
     335        /* Modify partition tables */
     336        rc = gpt_pte_update(part->label, &pte, part->index - 1);
     337        if (rc != EOK)
     338                return EIO;
     339
     340        list_remove(&part->llabel);
     341        free(part);
     342        return EOK;
     343}
     344
     345static void gpt_unused_pte(gpt_entry_t *pte)
     346{
     347        memset(pte, 0, sizeof(gpt_entry_t));
     348}
     349
     350static int gpt_part_to_pte(label_part_t *part, gpt_entry_t *pte)
     351{
     352        uint64_t eblock;
     353
     354        eblock = part->block0 + part->nblocks - 1;
     355        if (eblock < part->block0)
     356                return EINVAL;
     357
     358        memset(pte, 0, sizeof(gpt_entry_t));
     359        pte->part_type[0] = 0x12;
     360        pte->part_id[0] = 0x34;
     361        pte->start_lba = host2uint64_t_le(part->block0);
     362        pte->end_lba = host2uint64_t_le(eblock);
     363//      pte->attributes
     364//      pte->part_name
     365        return EOK;
    268366}
    269367
     
    301399}
    302400
     401/** Update partition table entry at specified index.
     402 *
     403 * Replace partition entry at index @a index with the contents of
     404 * @a pte.
     405 */
     406static int gpt_pte_update(label_t *label, gpt_entry_t *pte, int index)
     407{
     408        size_t pos;
     409        size_t offs;
     410        uint64_t ba;
     411        uint8_t *buf;
     412        gpt_entry_t *e;
     413        int i;
     414        int rc;
     415
     416        pos = index * label->lt.gpt.esize;
     417        offs = pos % label->block_size;
     418
     419        buf = calloc(1, label->block_size);
     420        if (buf == NULL)
     421                return ENOMEM;
     422
     423        /* For both partition tables: read, modify, write */
     424        for (i = 0; i < 2; i++) {
     425                ba = label->lt.gpt.ptable_ba[i] +
     426                    pos / label->block_size;
     427
     428                rc = block_read_direct(label->svcid, ba, 1, buf);
     429                if (rc != EOK) {
     430                        rc = EIO;
     431                        goto error;
     432                }
     433
     434                /* Replace single entry */
     435                e = (gpt_entry_t *)(&buf[offs]);
     436                *e = *pte;
     437
     438                rc = block_write_direct(label->svcid, ba, 1, buf);
     439                if (rc != EOK) {
     440                        rc = EIO;
     441                        goto error;
     442                }
     443        }
     444
     445        free(buf);
     446        return EOK;
     447error:
     448        free(buf);
     449        return rc;
     450}
     451
    303452/** @}
    304453 */
Note: See TracChangeset for help on using the changeset viewer.