Changeset d617050 in mainline for uspace/lib/mbr


Ignore:
Timestamp:
2013-04-20T01:13:44Z (12 years ago)
Author:
Dominik Taborsky (AT DOT) <brembyseznamcz>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
8f6c7785
Parents:
e91d17a
Message:

mbr && gpt fix

Location:
uspace/lib/mbr
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/mbr/libmbr.c

    re91d17a rd617050  
    4848static int decode_logical(mbr_t * mbr, mbr_partitions_t * p, mbr_part_t * ext);
    4949static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base);
     50static int check_overlap(mbr_part_t * p1, mbr_part_t * p2);
     51static int check_encaps(mbr_part_t * inner, mbr_part_t * outer);
     52static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee);
    5053
    5154/** Read MBR from specific device
     
    142145                if (mbr->raw_data.pte[i].ptype == PT_UNUSED)
    143146                        continue;
    144                
     147
    145148                p = malloc(sizeof(mbr_part_t));
    146149                if (p == NULL) {
     
    179182int mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle)
    180183{
    181         bool logical = false;
     184        //bool logical = false;
    182185        int i = 0;
    183186        int rc;
     
    185188        mbr_part_t * ext = (parts->l_extended == NULL) ? NULL
    186189                                        : list_get_instance(parts->l_extended, mbr_part_t, link);
    187        
    188         br_block_t * last_ebr = NULL;
    189         link_t * it;
    190        
     190
     191        //br_block_t * last_ebr = NULL;
     192        //link_t * it;
     193
    191194        DEBUG_PRINT_3(LIBMBR_NAME "Writing partitions: n_primary: %u, n_logical:%u, l_extended:%p", parts->n_primary, parts->n_logical, parts->l_extended);
    192        
     195
    193196        rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    194197        if (rc != EOK) {
     
    196199                return rc;
    197200        }
     201        /*
     202        // Encoding primary partitions
     203        for (i = 0; i < parts->n_primary; i++) {
     204                encode_part(p, &(mbr->raw_data.pte[i]), 0);
     205        }
     206
     207        // Writing MBR
     208        rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
     209        if (rc != EOK) {
     210                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     211                goto end;
     212        }
     213
     214        uint32_t base = ext->start_addr;
     215        uint32_t addr = base;
     216
     217        // Encoding and writing logical partitions
     218        mbr_part_foreach(parts, p) {
     219                if (p->ebr == NULL) {
     220                        p->ebr = alloc_br();
     221                        if (p->ebr == NULL)
     222                        {
     223                                rc = ENOMEM;
     224                                goto end;
     225                        }
     226                }
     227
     228
     229        }*/
     230
     231        link_t * l = parts->list.head.next;
     232
     233        // Encoding primary partitions
     234        for (i = 0; i < parts->n_primary; i++) {
     235                p = list_get_instance(l, mbr_part_t, link);
     236                encode_part(p, &(mbr->raw_data.pte[i]), 0);
     237                l = l->next;
     238        }
     239
     240        // Writing MBR
     241        rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
     242        if (rc != EOK) {
     243                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     244                goto end;
     245        }
    198246
    199247        if (ext == NULL)
    200248                goto no_extended;
    201249
     250
    202251        uint32_t base = ext->start_addr;
    203252        uint32_t addr = base;
     253
     254        // Encoding and writing first logical partition
     255        if (l != &(parts->list.head)) {
     256                p = list_get_instance(l, mbr_part_t, link);
     257                if (p->ebr == NULL) {
     258                        p->ebr = alloc_br();
     259                        if (p->ebr == NULL) {
     260                                rc = ENOMEM;
     261                                goto end;
     262                        }
     263                }
     264
     265                encode_part(p, &(p->ebr->pte[0]), base);
     266
     267                if (l->next == &(parts->list.head))
     268                        encode_part(NULL, &(p->ebr->pte[1]), base);
     269                else
     270                        encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base);
     271
     272
     273                rc = block_write_direct(dev_handle, base, 1, p->ebr);
     274                if (rc != EOK) {
     275                        DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     276                        goto end;
     277                }
     278
     279                l = l->next;
     280        }
     281
     282
     283
     284        // Encoding and writing logical partitions
     285        while (l != &(parts->list.head)) {
     286                p = list_get_instance(l, mbr_part_t, link);
     287                if (p->ebr == NULL) {
     288                        p->ebr = alloc_br();
     289                        if (p->ebr == NULL) {
     290                                rc = ENOMEM;
     291                                goto end;
     292                        }
     293                }
     294
     295                addr = p->start_addr - base;
     296                encode_part(p, &(p->ebr->pte[0]), addr);
     297
     298                if (l->next == &(parts->list.head))
     299                        encode_part(NULL, &(p->ebr->pte[1]), base);
     300                else
     301                        encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base);
     302
     303
     304                rc = block_write_direct(dev_handle, addr, 1, p->ebr);
     305                if (rc != EOK) {
     306                        DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     307                        goto end;
     308                }
     309
     310                l = l->next;
     311        }
     312
     313no_extended:
     314
     315        /*if (ext == NULL)
     316                goto no_extended;
     317
     318        uint32_t base = ext->start_addr;
     319        uint32_t addr;// = base;
    204320        uint32_t prev_addr;
    205321        mbr_part_t * prev_part = NULL;
     
    209325                if (mbr_get_flag(p, ST_LOGIC)) {
    210326                        // writing logical partition
    211                        
    212                         if (p->start_addr < base || p->start_addr + p->length > base + ext->length) {
    213                                 // out of bounds
    214                                 return EINVAL;
    215                         }
    216                        
    217                        
     327                        logical = true;
     328
    218329                        if (p->ebr == NULL) {
    219330                                p->ebr = alloc_br();
     
    225336                        }
    226337
    227                        
    228                        
    229                        
    230338                        if (prev_part != NULL) {
    231339                                // addr is the address of EBR
     
    243351                                addr = base;
    244352                                // base-1 means start_lba+1
    245                                 encode_part(p, &(p->ebr->pte[0]), base - 1);
     353                                // Fixed: mbr_add_partition now performs checks!nevim
     354                                encode_part(p, &(p->ebr->pte[0]), base);
    246355                        }
    247                        
     356
    248357                        //addr = p->start_addr;
    249358                        prev_addr = addr;
     
    260369                        ++i;
    261370                }
    262         }
     371        } //*/
    263372
    264373        /* If there was an extended but no logical, we should overwrite
     
    266375         * might be some garbage from the past.
    267376         */
    268        
     377        /*
    269378        last_ebr = prev_part->ebr;
    270        
     379
    271380        if (!logical)
    272381        {
     
    276385                        goto end;
    277386                }
    278                
     387
    279388                last_ebr->pte[0].ptype = PT_UNUSED;
    280389        }
    281        
    282        
     390
     391
    283392        encode_part(NULL, &(last_ebr->pte[1]), 0);
    284393        rc = block_write_direct(dev_handle, addr, 1, last_ebr);
    285        
     394
    286395        if (!logical)
    287396        {
    288397                free(last_ebr);
    289398        }
    290        
     399        */
     400        /*
    291401        if (rc != EOK) {
    292402                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
     
    297407
    298408no_extended:
    299 
     409        */
    300410        /*list_foreach(parts->list, it) {
    301411                p = list_get_instance(it, mbr_part_t, link);
     
    313423                }
    314424        }*/
    315        
     425        /*
    316426        it = parts->list.head.next;
    317427        for (i = 0; i < N_PRIMARY; i++) {
     
    329439
    330440                        }
    331                        
     441
    332442                        it = it->next;
    333443                } else {
     
    335445                }
    336446        }
    337        
     447
    338448
    339449skip:
     
    343453                goto end;
    344454        }
     455        */
    345456
    346457        /*
     
    405516
    406517        rc = EOK;
    407        
     518
    408519end:
    409520        block_fini(dev_handle);
     
    437548
    438549        list_initialize(&(parts->list));
    439        
     550
    440551        parts->n_primary = 0;
    441552        parts->n_logical = 0;
     
    445556}
    446557
    447 /** Add partition */
     558/** Add partition
     559 *      Performs checks, sorts the list.
     560 */
    448561int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p)
    449562{
    450         list_append(&(p->link), &(parts->list));
    451563        if (mbr_get_flag(p, ST_LOGIC)) {
     564                // adding logical part
     565                if (parts->l_extended == NULL) {
     566                        return ERR_NO_EXTENDED;
     567                }
     568                if (!check_encaps(p, list_get_instance(parts->l_extended, mbr_part_t, link))) {
     569                        return ERR_OUT_BOUNDS;
     570                }
     571
     572                mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link);
     573                mbr_part_foreach(parts, iter) {
     574                        if (mbr_get_flag(iter, ST_LOGIC)) {
     575                                if (check_overlap(p, iter)) {
     576                                        return ERR_OVERLAP;
     577                                }
     578                                if (check_preceeds(p, iter)) {
     579                                        last = iter;
     580                                        break;
     581                                }
     582                        }
     583                }
     584
     585                //list_prepend(&(p->link), &(parts->list));
     586                list_insert_before(&(p->link), &(last->link));
    452587                parts->n_logical += 1;
    453588        } else {
    454                 parts->n_primary += 1;
    455         }
    456         /* if we're adding new logical partition, we need 1 sector for the EBR
    457          * for that partition (including the next one); we'd better make sure here
    458          * before writing */
    459         if (mbr_get_flag(p, ST_LOGIC) && p->ebr == NULL) {
    460                 p->start_addr += 1;
    461                 p->length -= 1;
    462         }
    463         //FIXME: we can have multiple extended partitions! :-(
    464        
    465         return EOK;
     589                // adding primary
     590                if (parts->n_primary == 4) {
     591                        return ERR_PRIMARY_FULL;
     592                }
     593                if (p->type == PT_EXTENDED && parts->l_extended != NULL) {
     594                        return ERR_EXTENDED_PRESENT;
     595                }
     596
     597                if (list_empty(&(parts->list))) {
     598                        list_append(&(p->link), &(parts->list));
     599                } else {
     600                        mbr_part_foreach(parts, iter) {
     601                                if (mbr_get_flag(iter, ST_LOGIC)) {
     602                                        list_insert_before(&(p->link), &(iter->link));
     603                                        parts->n_primary += 1;
     604                                        break;
     605                                } else if (check_overlap(p, iter)) {
     606                                        return ERR_OVERLAP;
     607                                }
     608                        }
     609                }
     610        }
     611
     612        return ERR_OK;
    466613}
    467614
     
    469616int mbr_remove_partition(mbr_partitions_t * parts, size_t idx)
    470617{
    471         DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %d\n", idx);
     618        DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %zu\n", idx);
    472619        link_t * l = list_nth(&(parts->list), idx);
    473620        if (l == parts->l_extended) {
     
    482629                parts->n_primary -= 1;
    483630        }
    484        
    485        
     631
     632
    486633        mbr_free_partition(p);
    487        
     634
    488635        return EOK;
    489636}
     
    533680                mbr_free_partition(p);
    534681        }
    535        
     682
    536683        free(parts);
    537684}
     
    590737        if (rc != EOK)
    591738                return rc;
    592        
     739
    593740        ebr = alloc_br();
    594741        if (ebr == NULL) {
     
    606753                goto free_ebr_end;
    607754        }
    608        
     755
    609756        if (ebr->pte[0].ptype == PT_UNUSED) {
    610757                rc = EOK;
    611758                goto free_ebr_end;
    612759        }
    613        
     760
    614761        p = mbr_alloc_partition();
    615762        if (p == NULL) {
     
    617764                goto free_ebr_end;
    618765        }
    619        
     766
    620767
    621768        decode_part(&(ebr->pte[0]), p, base);
     
    625772
    626773        addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
    627        
     774
    628775        while (ebr->pte[1].ptype != PT_UNUSED) {
    629776                ebr = alloc_br();
     
    656803                addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
    657804        }
    658        
     805
    659806        rc = EOK;
    660        
     807
    661808free_ebr_end:
    662809        free(ebr);
    663        
     810
    664811end:
    665812        block_fini(mbr->device);
     
    690837}
    691838
     839static int check_overlap(mbr_part_t * p1, mbr_part_t * p2)
     840{
     841        if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) {
     842                return 0;
     843        } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) {
     844                return 0;
     845        }
     846
     847        return 1;
     848}
     849
     850static int check_encaps(mbr_part_t * inner, mbr_part_t * outer)
     851{
     852        if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) {
     853                return 0;
     854        } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) {
     855                return 0;
     856        }
     857
     858        return 1;
     859}
     860
     861static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee)
     862{
     863        return preceeder->start_addr < precedee->start_addr;
     864}
     865
     866
     867
  • uspace/lib/mbr/libmbr.h

    re91d17a rd617050  
    5252        printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2, arg3)
    5353#else
    54 #define DEBUG_PRINT_0(str) 
     54#define DEBUG_PRINT_0(str)
    5555#define DEBUG_PRINT_1(str, arg1)
    5656#define DEBUG_PRINT_2(str, arg1, arg2)
     
    8787        PT_GPT  = 0xEE,
    8888};
     89
     90typedef enum {
     91        /** No error */
     92        ERR_OK = 0,
     93        /** All primary partitions already present */
     94        ERR_PRIMARY_FULL,
     95        /** Extended partition already present */
     96        ERR_EXTENDED_PRESENT,
     97        /** No extended partition present */
     98        ERR_NO_EXTENDED,
     99        /** Partition overlapping */
     100        ERR_OVERLAP,
     101        /** Logical partition out of bounds */
     102        ERR_OUT_BOUNDS,
     103} MBR_ERR_VAL;
     104
    89105
    90106/** Structure of a partition table entry */
     
    146162        /** Number of primary partitions */
    147163        unsigned char n_primary;
    148         /** Link to the extended partition in the list */
     164        /** Index to the extended partition in the array */
    149165        link_t * l_extended;
    150166        /** Number of logical partitions */
    151167        unsigned int n_logical;
    152         /** Partition linked list */
     168        /** Logical partition linked list */
    153169        list_t list;
    154170} mbr_partitions_t;
Note: See TracChangeset for help on using the changeset viewer.