Ignore:
File:
1 edited

Legend:

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

    r6e8e4e19 r44c4886  
    5252static int check_encaps(mbr_part_t *, mbr_part_t *);
    5353static int check_preceeds(mbr_part_t *, mbr_part_t *);
    54 static mbr_err_val mbr_add_primary(mbr_label_t *label, mbr_part_t *p);
    55 static mbr_err_val mbr_add_logical(mbr_label_t *label, mbr_part_t *p);
    5654
    5755/** Allocate and initialize mbr_label_t structure */
     
    9492 */
    9593int mbr_read_mbr(mbr_label_t *label, service_id_t dev_handle)
    96 {
    97         if (label == NULL)
    98                 return EINVAL;
    99        
     94{       
    10095        int rc;
    10196       
     
    173168        mbr_part_t *ext = NULL;
    174169        //mbr_partitions_t *parts;
    175        
     170        printf("check\n");
    176171        if (label->parts != NULL)
    177172                mbr_free_partitions(label->parts);
    178        
     173        printf("check2\n");
    179174        label->parts = mbr_alloc_partitions();
    180175        if (label->parts == NULL) {
    181176                return ENOMEM;
    182177        }
    183        
     178        printf("primary\n");
    184179        /* Generate the primary partitions */
    185180        for (i = 0; i < N_PRIMARY; ++i) {
    186181                if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED)
    187182                        continue;
    188                
     183                printf("pcheck1\n");
    189184                p = mbr_alloc_partition();
    190185                if (p == NULL) {
     
    193188                        return ENOMEM;
    194189                }
    195                
     190                printf("pcheck2\n");
    196191                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);
    198192                mbr_set_flag(p, ST_LOGIC, false);
    199193                rc = mbr_add_partition(label, p);
     
    204198                        return EINVAL;
    205199                }
    206                
     200                printf("pcheck3\n");
    207201                if (rc_ext) {
    208202                        ext = p;
    209                         printf("ext: %u %u\n", p->start_addr, p->length);
    210                         label->parts->l_extended = &p->link;
    211                 }
    212         }
    213        
     203                        label->parts->l_extended = list_nth(&(label->parts->list), i);
     204                }
     205                printf("pcheck4\n");
     206        }
     207        printf("logical\n");
    214208        /* Fill in the primary partitions and generate logical ones, if any */
    215209        rc = decode_logical(label, ext);
    216210        if (rc != EOK) {
    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));
     211                printf(LIBMBR_NAME ": Error occured during decoding the MBR.\n" \
     212                           LIBMBR_NAME ": Partition list may be incomplete.\n");
    219213                return rc;
    220214        }
    221        
     215        printf("finish\n");
    222216        return EOK;
    223217}
     
    246240       
    247241        /* Encoding primary partitions */
    248         for (i = 0; i < N_PRIMARY; i++) {
     242        for (i = 0; i < label->parts->n_primary; i++) {
    249243                p = list_get_instance(l, mbr_part_t, link);     
    250                 printf("status: %hu\n", p->status);
    251244                encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false);
    252245                l = l->next;
     
    260253        }
    261254       
    262         if (ext == NULL) {
    263                 rc = EOK;
     255        if (ext == NULL)
    264256                goto end;
    265         }
    266257       
    267258        uint32_t base = ext->start_addr;
    268         mbr_part_t *prev_p;
     259        mbr_part_t * prev_p;
    269260       
    270261        /* Note for future changes: Some thought has been put into design
     
    290281                }
    291282                free(tmp);
    292                 rc = EOK;
    293283                goto end;
    294284        }
    295285       
    296286        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);
    332287       
    333288        /* Encoding and writing logical partitions */
     
    335290                p = list_get_instance(l, mbr_part_t, link);
    336291               
     292                /* Checking whether EBR address makes sense. If not, we take a guess.
     293                 * So far this is simple, we just take the first preceeding sector.
     294                 * Fdisk always reserves at least 2048 sectors (1MiB), so it can have
     295                 * the EBR aligned as well as the partition itself. Parted reserves
     296                 * minimum one sector, like we do.
     297                 *
     298                 * Note that we know there is at least one sector free from previous checks.
     299                 * Also note that the user can set ebr_addr to their liking (if it's valid). */         
     300                if (p->ebr_addr >= p->start_addr || p->ebr_addr <= (prev_p->start_addr + prev_p->length)) {
     301                        p->ebr_addr = p->start_addr - 1;
     302                        DEBUG_PRINT_0(LIBMBR_NAME ": Warning: invalid EBR address.\n");
     303                }
    337304               
    338305                encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false);
     
    423390mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p)
    424391{
    425         int rc1, rc2;
     392        int rc;
     393        mbr_partitions_t *parts = label->parts;
     394       
    426395        aoff64_t nblocks;
    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));
     396        printf("add1.\n");
     397        rc = block_init(EXCHANGE_ATOMIC, label->device, 512);
     398        if (rc != EOK) {
     399                printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
    431400                return ERR_LIBBLOCK;
    432401        }
    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));
     402        printf("add2.\n");
     403        rc = block_get_nblocks(label->device, &nblocks);
     404        block_fini(label->device);
     405        if (rc != EOK) {
     406                printf(LIBMBR_NAME ": Error while getting number of blocks: %d - %s.\n", rc, str_error(rc));
    441407                return ERR_LIBBLOCK;
    442408        }
    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))
     409        printf("add3.\n");
     410        if (mbr_get_flag(p, ST_LOGIC)) {
    454411                /* adding logical partition */
    455                 return mbr_add_logical(label, p);
    456         else
     412               
     413                /* is there any extended partition? */
     414                if (parts->l_extended == NULL)
     415                        return ERR_NO_EXTENDED;
     416               
     417                /* is the logical partition inside the extended one? */
     418                mbr_part_t *ext = list_get_instance(parts->l_extended, mbr_part_t, link);
     419                if (!check_encaps(p, ext))
     420                        return ERR_OUT_BOUNDS;
     421               
     422                /* find a place for the new partition in a sorted linked list */
     423                //mbr_part_t *last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link);
     424                mbr_part_t *iter;
     425                //uint32_t ebr_space = 1;
     426                mbr_part_foreach(parts, iter) {
     427                        if (mbr_get_flag(iter, ST_LOGIC)) {
     428                                if (check_overlap(p, iter))
     429                                        return ERR_OVERLAP;
     430                                if (check_preceeds(iter, p)) {
     431                                        /* checking if there's at least one sector of space preceeding */
     432                                        if ((iter->start_addr + iter->length) >= p->start_addr - 1)
     433                                                return ERR_NO_EBR;
     434                                } else {
     435                                        /* checking if there's at least one sector of space following (for following partitions's EBR) */
     436                                        if ((p->start_addr + p->length) >= iter->start_addr - 1)
     437                                                return ERR_NO_EBR;
     438                                }
     439                        }
     440                }
     441               
     442                /* alloc EBR if it's not already there */
     443                if (p->ebr == NULL) {
     444                        p->ebr = alloc_br();
     445                        if (p->ebr == NULL) {
     446                                return ERR_NOMEM;
     447                        }
     448                }
     449               
     450                /* add it */
     451                list_append(&(p->link), &(parts->list));
     452                parts->n_logical += 1;
     453        } else {
    457454                /* adding primary */
    458                 return mbr_add_primary(label, p);
     455               
     456                if (parts->n_primary == 4) {
     457                        return ERR_PRIMARY_FULL;
     458                }
     459               
     460                /* Check if partition makes space for MBR itself. */
     461                if (p->start_addr == 0 || ((aoff64_t) p->start_addr) + p->length >= nblocks) {
     462                        return ERR_OUT_BOUNDS;
     463                }
     464                printf("add4.\n");
     465                /* if it's extended, is there any other one? */
     466                if ((p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA) && parts->l_extended != NULL) {
     467                        return ERR_EXTENDED_PRESENT;
     468                }
     469                printf("add5.\n");
     470                /* find a place and add it */
     471                mbr_part_t *iter;
     472                mbr_part_t *empty = NULL;
     473                mbr_part_foreach(parts, iter) {
     474                        printf("type: %x\n", iter->type);
     475                        if (iter->type == PT_UNUSED) {
     476                                if (empty == NULL)
     477                                        empty = iter;
     478                        } else if (check_overlap(p, iter))
     479                                return ERR_OVERLAP;
     480                }
     481                printf("add6. %p, %p\n", empty, p);
     482                list_insert_after(&(p->link), &(empty->link));
     483                printf("add6.1.\n");
     484                list_remove(&(empty->link));
     485                printf("add6.2.\n");
     486                free(empty);
     487                printf("add7.\n");
     488                parts->n_primary += 1;
     489               
     490                if (p->type == PT_EXTENDED || p->type == PT_EXTENDED_LBA)
     491                        parts->l_extended = &(p->link);
     492        }
     493        printf("add8.\n");
     494        return ERR_OK;
    459495}
    460496
     
    533569void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value)
    534570{
    535         uint16_t status = p->status;
     571        uint8_t status = p->status;
    536572
    537573        if (value)
     
    543579}
    544580
    545 /** Get next aligned address */
     581/** Get next aligned address (in sectors!) */
    546582uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment)
    547583{
    548584        uint32_t div = addr / alignment;
    549585        return (div + 1) * alignment;
    550 }
    551 
    552 list_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 
    560 mbr_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 
    569 mbr_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;
    576586}
    577587
     
    617627        trgt->type = src->ptype;
    618628
    619         trgt->status = (trgt->status & 0xFF00) | (uint16_t) src->status;
     629        /* Checking only 0x80; otherwise writing will fix to 0x00 */
     630        trgt->status = (trgt->status & 0xFF00) | src->status;
    620631
    621632        trgt->start_addr = uint32_t_le2host(src->first_lba) + base;
     
    680691       
    681692        while (ebr->pte[1].ptype != PT_UNUSED) {
    682                
    683693                ebr = alloc_br();
    684694                if (ebr == NULL) {
     
    702712                        goto free_ebr_end;
    703713                }
     714               
    704715               
    705716                decode_part(&(ebr->pte[0]), p, addr);
     
    748759                        trgt->length = host2uint32_t_le(src->length);
    749760                }
    750                
    751                 if (trgt->ptype == PT_UNUSED)
    752                         memset(trgt, 0, sizeof(pt_entry_t));
    753761        } else {
    754                 memset(trgt, 0, sizeof(pt_entry_t));
     762                trgt->status = 0;
     763                trgt->first_chs[0] = 0;
     764                trgt->first_chs[1] = 0;
     765                trgt->first_chs[2] = 0;
     766                trgt->ptype = 0;
     767                trgt->last_chs[0] = 0;
     768                trgt->last_chs[1] = 0;
     769                trgt->last_chs[2] = 0;
     770                trgt->first_lba = 0;
     771                trgt->length = 0;
    755772        }
    756773}
     
    762779static int check_overlap(mbr_part_t * p1, mbr_part_t * p2)
    763780{
    764         if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) {
     781        if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length < p2->start_addr) {
    765782                return 0;
    766         } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) {
     783        } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length < p1->start_addr) {
    767784                return 0;
    768785        }
     
    795812}
    796813
    797 mbr_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 
    836 mbr_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 
     814
     815
     816
Note: See TracChangeset for help on using the changeset viewer.