Changeset 6e8e4e19 in mainline for uspace/lib/mbr/libmbr.c


Ignore:
Timestamp:
2013-06-16T14:50:59Z (11 years ago)
Author:
Dominik Taborsky (AT DOT) <brembyseznamcz>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1c8bfe8
Parents:
c9f61150
Message:

libmbr & hdisk changes, fixes, updates

File:
1 edited

Legend:

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

    rc9f61150 r6e8e4e19  
    5252static int check_encaps(mbr_part_t *, mbr_part_t *);
    5353static int check_preceeds(mbr_part_t *, mbr_part_t *);
     54static mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *p);
     55static mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *p);
    5456
    5557/** Allocate and initialize mbr_label_t structure */
     
    171173        mbr_part_t *ext = NULL;
    172174        //mbr_partitions_t *parts;
    173         printf("check\n");
     175       
    174176        if (label->parts != NULL)
    175177                mbr_free_partitions(label->parts);
    176         printf("check2\n");
     178       
    177179        label->parts = mbr_alloc_partitions();
    178180        if (label->parts == NULL) {
    179181                return ENOMEM;
    180182        }
    181         printf("primary\n");
     183       
    182184        /* Generate the primary partitions */
    183185        for (i = 0; i < N_PRIMARY; ++i) {
    184186                if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED)
    185187                        continue;
    186                 printf("pcheck1\n");
     188               
    187189                p = mbr_alloc_partition();
    188190                if (p == NULL) {
     
    191193                        return ENOMEM;
    192194                }
    193                 printf("pcheck2\n");
     195               
    194196                rc_ext = decode_part(&(label->mbr->raw_data.pte[i]), p, 0);
     197                printf("p: %d %u %u\n", rc_ext, p->start_addr, p->length);
    195198                mbr_set_flag(p, ST_LOGIC, false);
    196199                rc = mbr_add_partition(label, p);
     
    201204                        return EINVAL;
    202205                }
    203                 printf("pcheck3\n");
     206               
    204207                if (rc_ext) {
    205208                        ext = p;
    206                         label->parts->l_extended = list_nth(&(label->parts->list), i);
    207                 }
    208                 printf("pcheck4\n");
    209         }
    210         printf("logical\n");
     209                        printf("ext: %u %u\n", p->start_addr, p->length);
     210                        label->parts->l_extended = &p->link;
     211                }
     212        }
     213       
    211214        /* Fill in the primary partitions and generate logical ones, if any */
    212215        rc = decode_logical(label, ext);
    213216        if (rc != EOK) {
    214                 printf(LIBMBR_NAME ": Error occured during decoding the MBR.\n" \
    215                            LIBMBR_NAME ": Partition list may be incomplete.\n");
     217                printf(LIBMBR_NAME ": Error during decoding logical partitions: %d - %s.\n" \
     218                           LIBMBR_NAME ": Partition list may be incomplete.\n", rc, str_error(rc));
    216219                return rc;
    217220        }
    218         printf("finish\n");
     221       
    219222        return EOK;
    220223}
     
    243246       
    244247        /* Encoding primary partitions */
    245         for (i = 0; i < label->parts->n_primary; i++) {
     248        for (i = 0; i < N_PRIMARY; i++) {
    246249                p = list_get_instance(l, mbr_part_t, link);     
     250                printf("status: %hu\n", p->status);
    247251                encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false);
    248252                l = l->next;
     
    256260        }
    257261       
    258         if (ext == NULL)
     262        if (ext == NULL) {
     263                rc = EOK;
    259264                goto end;
     265        }
    260266       
    261267        uint32_t base = ext->start_addr;
    262         mbr_part_t * prev_p;
     268        mbr_part_t *prev_p;
    263269       
    264270        /* Note for future changes: Some thought has been put into design
     
    284290                }
    285291                free(tmp);
     292                rc = EOK;
    286293                goto end;
    287294        }
    288295       
    289296        prev_p = p;
     297       
     298        /* Check EBR addresses
     299         * This piece of code saves previous EBR placements from other
     300         * software. But if our user modifies the logical partition chain,
     301         * we have to fix those placements if needed.*/
     302        link_t *l_ebr = l;
     303        link_t *l_iter;
     304        mbr_part_t *tmp = mbr_alloc_partition();
     305        tmp->length = 1;
     306        while (l_ebr != &(label->parts->list.head)) {
     307                p = list_get_instance(l_ebr, mbr_part_t, link);
     308                tmp->start_addr = p->ebr_addr;
     309               
     310                l_iter = l;
     311                while (l_iter != &(label->parts->list.head)) {
     312                        /* Checking whether EBR address makes sense. If not, we take a guess.
     313                         * So far this is simple, we just take the first preceeding sector.
     314                         * Fdisk always reserves at least 2048 sectors (1MiB), so it can have
     315                         * the EBR aligned as well as the partition itself. Parted reserves
     316                         * minimum one sector, like we do.
     317                         *
     318                         * Note that we know there is at least one sector free from previous checks.
     319                         * Also note that the user can set ebr_addr to their liking (if it's valid). */         
     320                        if (p->ebr_addr < base || p->ebr_addr >= base + ext->length ||
     321                          check_overlap(tmp, list_get_instance(l_iter, mbr_part_t, link))) {
     322                                p->ebr_addr = p->start_addr - 1;
     323                                break;
     324                        }
     325                       
     326                        l_iter = l_iter->next;
     327                }
     328               
     329                l_ebr = l_ebr->next;
     330        }
     331        mbr_free_partition(tmp);
    290332       
    291333        /* Encoding and writing logical partitions */
     
    293335                p = list_get_instance(l, mbr_part_t, link);
    294336               
    295                 /* Checking whether EBR address makes sense. If not, we take a guess.
    296                  * So far this is simple, we just take the first preceeding sector.
    297                  * Fdisk always reserves at least 2048 sectors (1MiB), so it can have
    298                  * the EBR aligned as well as the partition itself. Parted reserves
    299                  * minimum one sector, like we do.
    300                  *
    301                  * Note that we know there is at least one sector free from previous checks.
    302                  * Also note that the user can set ebr_addr to their liking (if it's valid). */         
    303                 if (p->ebr_addr >= p->start_addr || p->ebr_addr <= (prev_p->start_addr + prev_p->length)) {
    304                         p->ebr_addr = p->start_addr - 1;
    305                         DEBUG_PRINT_0(LIBMBR_NAME ": Warning: invalid EBR address.\n");
    306                 }
    307337               
    308338                encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false);
     
    393423mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p)
    394424{
    395         int rc;
    396         mbr_partitions_t *parts = label->parts;
    397        
     425        int rc1, rc2;
    398426        aoff64_t nblocks;
    399         printf("add1.\n");
    400         rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
    401         if (rc != EOK) {
    402                 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
     427       
     428        rc1 = block_init(EXCHANGE_ATOMIC, label->device, 512);
     429        if (rc1 != EOK && rc1 != EEXIST) {
     430                printf(LIBMBR_NAME ": Error during libblock init: %d - %s.\n", rc1, str_error(rc1));
    403431                return ERR_LIBBLOCK;
    404432        }
    405         printf("add2.\n");
    406         rc = block_get_nblocks(label->device, &nblocks);
    407         block_fini(label->device);
    408         if (rc != EOK) {
    409                 printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
     433       
     434        rc2 = block_get_nblocks(label->device, &nblocks);
     435       
     436        if (rc1 != EEXIST)
     437                block_fini(label->device);
     438       
     439        if (rc2 != EOK) {
     440                printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc2, str_error(rc2));
    410441                return ERR_LIBBLOCK;
    411442        }
    412         printf("add3.\n");
    413         if (mbr_get_flag(p, ST_LOGIC)) {
     443       
     444        if ((aoff64_t) p->start_addr + p->length > nblocks)
     445                return ERR_OUT_BOUNDS;
     446       
     447        if (label->parts == NULL) {
     448                label->parts = mbr_alloc_partitions();
     449                if (label->parts == NULL)
     450                        return ENOMEM; //FIXME! merge mbr_err_val into errno.h
     451        }
     452       
     453        if (mbr_get_flag(p, ST_LOGIC))
    414454                /* adding logical partition */
    415                
    416                 /* is there any extended partition? */
    417                 if (parts->l_extended == NULL)
    418                         return ERR_NO_EXTENDED;
    419                
    420                 /* is the logical partition inside the extended one? */
    421                 mbr_part_t *ext = list_get_instance(parts->l_extended, mbr_part_t, link);
    422                 if (!check_encaps(p, ext))
    423                         return ERR_OUT_BOUNDS;
    424                
    425                 /* find a place for the new partition in a sorted linked list */
    426                 //mbr_part_t *last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link);
    427                 mbr_part_t *iter;
    428                 //uint32_t ebr_space = 1;
    429                 mbr_part_foreach(parts, iter) {
    430                         if (mbr_get_flag(iter, ST_LOGIC)) {
    431                                 if (check_overlap(p, iter))
    432                                         return ERR_OVERLAP;
    433                                 if (check_preceeds(iter, p)) {
    434                                         /* checking if there's at least one sector of space preceeding */
    435                                         if ((iter->start_addr + iter->length) >= p->start_addr - 1)
    436                                                 return ERR_NO_EBR;
    437                                 } else {
    438                                         /* checking if there's at least one sector of space following (for following partitions's EBR) */
    439                                         if ((p->start_addr + p->length) >= iter->start_addr - 1)
    440                                                 return ERR_NO_EBR;
    441                                 }
    442                         }
    443                 }
    444                
    445                 /* alloc EBR if it's not already there */
    446                 if (p->ebr == NULL) {
    447                         p->ebr = alloc_br();
    448                         if (p->ebr == NULL) {
    449                                 return ERR_NOMEM;
    450                         }
    451                 }
    452                
    453                 /* add it */
    454                 list_append(&(p->link), &(parts->list));
    455                 parts->n_logical += 1;
    456         } else {
     455                return mbr_add_logical(label, p);
     456        else
    457457                /* adding primary */
    458                
    459                 if (parts->n_primary == 4) {
    460                         return ERR_PRIMARY_FULL;
    461                 }
    462                
    463                 /* Check if partition makes space for MBR itself. */
    464                 if (p->start_addr == 0 || ((aoff64_t) p->start_addr) + p->length >= nblocks) {
    465                         return ERR_OUT_BOUNDS;
    466                 }
    467                 printf("add4.\n");
    468                 /* if it's extended, is there any other one? */
    469                 if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && parts->l_extended != NULL) {
    470                         return ERR_EXTENDED_PRESENT;
    471                 }
    472                 printf("add5.\n");
    473                 /* find a place and add it */
    474                 mbr_part_t *iter;
    475                 mbr_part_t *empty = NULL;
    476                 mbr_part_foreach(parts, iter) {
    477                         printf("type: %x\n", iter->type);
    478                         if (iter->type == PT_UNUSED) {
    479                                 if (empty == NULL)
    480                                         empty = iter;
    481                         } else if (check_overlap(p, iter))
    482                                 return ERR_OVERLAP;
    483                 }
    484                 printf("add6. %p, %p\n", empty, p);
    485                 list_insert_after(&(p->link), &(empty->link));
    486                 printf("add6.1.\n");
    487                 list_remove(&(empty->link));
    488                 printf("add6.2.\n");
    489                 free(empty);
    490                 printf("add7.\n");
    491                 parts->n_primary += 1;
    492                
    493                 if (p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)
    494                         parts->l_extended = &(p->link);
    495         }
    496         printf("add8.\n");
    497         return ERR_OK;
     458                return mbr_add_primary(label, p);
    498459}
    499460
     
    572533void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value)
    573534{
    574         uint8_t status = p->status;
     535        uint16_t status = p->status;
    575536
    576537        if (value)
     
    582543}
    583544
    584 /** Get next aligned address (in sectors!) */
     545/** Get next aligned address */
    585546uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment)
    586547{
    587548        uint32_t div = addr / alignment;
    588549        return (div + 1) * alignment;
     550}
     551
     552list_t * mbr_get_list(mbr_label_t *label)
     553{
     554        if (label->parts != NULL)
     555                return &(label->parts->list);
     556        else
     557                return NULL;
     558}
     559
     560mbr_part_t * mbr_get_first_partition(mbr_label_t *label)
     561{
     562        list_t *list = mbr_get_list(label);
     563        if (list != NULL && !list_empty(list))
     564                return list_get_instance(list->head.next, mbr_part_t, link);
     565        else
     566                return NULL;
     567}
     568
     569mbr_part_t * mbr_get_next_partition(mbr_label_t *label, mbr_part_t *p)
     570{
     571        list_t *list = mbr_get_list(label);
     572        if (list != NULL && &(p->link) != list_last(list))
     573                return list_get_instance(p->link.next, mbr_part_t, link);
     574        else
     575                return NULL;
    589576}
    590577
     
    630617        trgt->type = src->ptype;
    631618
    632         /* Checking only 0x80; otherwise writing will fix to 0x00 */
    633         trgt->status = (trgt->status & 0xFF00) | src->status;
     619        trgt->status = (trgt->status & 0xFF00) | (uint16_t) src->status;
    634620
    635621        trgt->start_addr = uint32_t_le2host(src->first_lba) + base;
     
    694680       
    695681        while (ebr->pte[1].ptype != PT_UNUSED) {
     682               
    696683                ebr = alloc_br();
    697684                if (ebr == NULL) {
     
    715702                        goto free_ebr_end;
    716703                }
    717                
    718704               
    719705                decode_part(&(ebr->pte[0]), p, addr);
     
    762748                        trgt->length = host2uint32_t_le(src->length);
    763749                }
     750               
     751                if (trgt->ptype == PT_UNUSED)
     752                        memset(trgt, 0, sizeof(pt_entry_t));
    764753        } else {
    765                 trgt->status = 0;
    766                 trgt->first_chs[0] = 0;
    767                 trgt->first_chs[1] = 0;
    768                 trgt->first_chs[2] = 0;
    769                 trgt->ptype = 0;
    770                 trgt->last_chs[0] = 0;
    771                 trgt->last_chs[1] = 0;
    772                 trgt->last_chs[2] = 0;
    773                 trgt->first_lba = 0;
    774                 trgt->length = 0;
     754                memset(trgt, 0, sizeof(pt_entry_t));
    775755        }
    776756}
     
    782762static int check_overlap(mbr_part_t * p1, mbr_part_t * p2)
    783763{
    784         if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length < p2->start_addr) {
     764        if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) {
    785765                return 0;
    786         } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length < p1->start_addr) {
     766        } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) {
    787767                return 0;
    788768        }
     
    815795}
    816796
    817 
    818 
    819 
     797mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *p)
     798{
     799        if (label->parts->n_primary == 4) {
     800                return ERR_PRIMARY_FULL;
     801        }
     802       
     803        /* Check if partition makes space for MBR itself. */
     804        if (p->start_addr == 0) {
     805                return ERR_OUT_BOUNDS;
     806        }
     807       
     808        /* if it's extended, is there any other one? */
     809        if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && label->parts->l_extended != NULL) {
     810                return ERR_EXTENDED_PRESENT;
     811        }
     812       
     813        /* find a place and add it */
     814        mbr_part_t *iter;
     815        mbr_part_t *empty = NULL;
     816        mbr_part_foreach(label, iter) {
     817                if (iter->type == PT_UNUSED) {
     818                        if (empty == NULL)
     819                                empty = iter;
     820                } else if (check_overlap(p, iter))
     821                        return ERR_OVERLAP;
     822        }
     823       
     824        list_insert_after(&(p->link), &(empty->link));
     825        list_remove(&(empty->link));
     826        free(empty);
     827       
     828        label->parts->n_primary += 1;
     829       
     830        if (p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)
     831                label->parts->l_extended = &(p->link);
     832       
     833        return EOK;
     834}
     835
     836mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *p)
     837{
     838        /* is there any extended partition? */
     839        if (label->parts->l_extended == NULL)
     840                return ERR_NO_EXTENDED;
     841       
     842        /* is the logical partition inside the extended one? */
     843        mbr_part_t *ext = list_get_instance(label->parts->l_extended, mbr_part_t, link);
     844        if (!check_encaps(p, ext))
     845                return ERR_OUT_BOUNDS;
     846       
     847        /* find a place for the new partition in a sorted linked list */
     848        bool first_logical = true;
     849        mbr_part_t *iter;
     850        mbr_part_foreach(label, iter) {
     851                if (mbr_get_flag(iter, ST_LOGIC)) {
     852                        if (check_overlap(p, iter))
     853                                return ERR_OVERLAP;
     854                        if (check_preceeds(iter, p)) {
     855                                /* checking if there's at least one sector of space preceeding */
     856                                if ((iter->start_addr + iter->length) >= p->start_addr - 1)
     857                                        return ERR_NO_EBR;
     858                        } else if (first_logical){
     859                                /* First logical partition's EBR is before every other
     860                                 * logical partition. Thus we don't check if this partition
     861                                 * leaves enough space for it. */
     862                                first_logical = false;
     863                        } else {
     864                                /* checking if there's at least one sector of space following (for following partitions's EBR) */
     865                                if ((p->start_addr + p->length) >= iter->start_addr - 1)
     866                                        return ERR_NO_EBR;
     867                        }
     868                }
     869        }
     870       
     871        /* alloc EBR if it's not already there */
     872        if (p->ebr == NULL) {
     873                p->ebr = alloc_br();
     874                if (p->ebr == NULL) {
     875                        return ERR_NOMEM;
     876                }
     877        }
     878       
     879        /* add it */
     880        list_append(&(p->link), &(label->parts->list));
     881        label->parts->n_logical += 1;
     882       
     883        return EOK;
     884}
     885
     886
     887
Note: See TracChangeset for help on using the changeset viewer.