Changeset 30440ed in mainline for uspace/lib/mbr/libmbr.c


Ignore:
Timestamp:
2013-04-08T23:15:42Z (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:
256cbfe
Parents:
271e24a
Message:

save progress

File:
1 edited

Legend:

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

    r271e24a r30440ed  
    150150                        return NULL;
    151151                }
    152                 list_append(&(p->link), &(parts->list));
     152                //list_append(&(p->link), &(parts->list));
    153153                p->ebr = NULL;
    154                 if (decode_part(&(mbr->raw_data.pte[i]), p, 0))
     154                if (decode_part(&(mbr->raw_data.pte[i]), p, 0)) {
    155155                        ext = p;
     156                        parts->l_extended = list_last(&(parts->list));
     157                }
     158                mbr_set_flag(p, ST_LOGIC, false);
     159                mbr_add_partition(parts, p);
    156160        }
    157161
     
    183187       
    184188        br_block_t * last_ebr = NULL;
    185 
    186 
     189        link_t * it;
     190       
     191        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       
    187193        rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512);
    188194        if (rc != EOK) {
     195                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
    189196                return rc;
    190197        }
     
    193200                goto no_extended;
    194201
    195         aoff64_t addr = ext->start_addr;
     202        uint32_t base = ext->start_addr;
     203        uint32_t addr = base;
     204        uint32_t prev_addr;
    196205        mbr_part_t * prev_part = NULL;
    197206
    198         list_foreach(parts->list, it) {
    199                 p = list_get_instance(it, mbr_part_t, link);
     207        list_foreach(parts->list, iter) {
     208                p = list_get_instance(iter, mbr_part_t, link);
    200209                if (mbr_get_flag(p, ST_LOGIC)) {
    201210                        // writing logical partition
    202 
     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                       
    203218                        if (p->ebr == NULL) {
    204219                                p->ebr = alloc_br();
     
    210225                        }
    211226
    212 
    213                         encode_part(p, &(p->ebr->pte[0]), addr);
     227                       
     228                       
     229                       
    214230                        if (prev_part != NULL) {
    215                                 encode_part(p, &(prev_part->ebr->pte[1]), ext->start_addr);
    216                                 rc = block_write_direct(dev_handle, p->start_addr, 1, prev_part->ebr);
    217                                 if (rc != EOK)
     231                                // addr is the address of EBR
     232                                addr = p->start_addr - base;
     233                                // base-1 means start_lba+1
     234                                encode_part(p, &(p->ebr->pte[0]), addr - 1);
     235                                encode_part(p, &(prev_part->ebr->pte[1]), base);
     236                                rc = block_write_direct(dev_handle, prev_addr, 1, prev_part->ebr);
     237                                if (rc != EOK) {
     238                                        DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
    218239                                        goto end;
     240                                }
     241                        } else {
     242                                // addr is the address of EBR
     243                                addr = base;
     244                                // base-1 means start_lba+1
     245                                encode_part(p, &(p->ebr->pte[0]), base - 1);
    219246                        }
    220247                       
    221                         addr = p->start_addr;
     248                        //addr = p->start_addr;
     249                        prev_addr = addr;
    222250                        prev_part = p;
    223251                } else {
     
    261289        }
    262290       
    263         if (rc != EOK)
     291        if (rc != EOK) {
     292                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
    264293                goto end;
     294        }
    265295
    266296        goto skip;
     
    268298no_extended:
    269299
    270         list_foreach(parts->list, it) {
     300        /*list_foreach(parts->list, it) {
    271301                p = list_get_instance(it, mbr_part_t, link);
    272302                if (mbr_get_flag(p, ST_LOGIC)) {
     
    282312                        ++i;
    283313                }
    284         }
     314        }*/
     315       
     316        it = parts->list.head.next;
     317        for (i = 0; i < N_PRIMARY; i++) {
     318                if (it != &parts->list.head) {
     319                        p = list_get_instance(it, mbr_part_t, link);
     320                        if (mbr_get_flag(p, ST_LOGIC)) {
     321                                // extended does not exist, fail
     322                                return EINVAL;
     323                        } else {
     324                                // writing primary partition
     325                                if (i >= 4)
     326                                        return EINVAL;
     327
     328                                encode_part(p, &(mbr->raw_data.pte[i]), 0);
     329
     330                        }
     331                       
     332                        it = it->next;
     333                } else {
     334                        encode_part(NULL, &(mbr->raw_data.pte[i]), 0);
     335                }
     336        }
     337       
    285338
    286339skip:
    287340        rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));
    288         if (rc != EOK)
     341        if (rc != EOK) {
     342                DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));
    289343                goto end;
     344        }
    290345
    291346        /*
     
    382437
    383438        list_initialize(&(parts->list));
     439       
     440        parts->n_primary = 0;
     441        parts->n_logical = 0;
     442        parts->l_extended = NULL;
    384443
    385444        return parts;
     
    387446
    388447/** Add partition */
    389 int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * partition)
    390 {
    391         list_append(&(partition->link), &(parts->list));
     448int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p)
     449{
     450        list_append(&(p->link), &(parts->list));
     451        if (mbr_get_flag(p, ST_LOGIC)) {
     452                parts->n_logical += 1;
     453        } 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       
    392465        return EOK;
    393466}
     
    396469int mbr_remove_partition(mbr_partitions_t * parts, size_t idx)
    397470{
     471        DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %d\n", idx);
    398472        link_t * l = list_nth(&(parts->list), idx);
     473        if (l == parts->l_extended) {
     474                DEBUG_PRINT_0(LIBMBR_NAME "Removing extended partition.\n");
     475                parts->l_extended = NULL;
     476        }
    399477        list_remove(l);
    400478        mbr_part_t * p = list_get_instance(l, mbr_part_t, link);
     479        if (mbr_get_flag(p, ST_LOGIC)) {
     480                parts->n_logical -= 1;
     481        } else {
     482                parts->n_primary -= 1;
     483        }
     484       
     485       
    401486        mbr_free_partition(p);
    402487       
     
    448533                mbr_free_partition(p);
    449534        }
     535       
     536        free(parts);
    450537}
    451538
     
    465552}
    466553
    467 /** Parse partition entry to mbr_part_t */
     554/** Parse partition entry to mbr_part_t
     555 * @return              returns 1, if extended partition, 0 otherwise
     556 * */
    468557static int decode_part(pt_entry_t * src, mbr_part_t * trgt, uint32_t base)
    469558{
     
    480569}
    481570
    482 /** Parse MBR contents to mbr_part_t list
    483  * parameter 'p' is allocated for only used primary partitions
    484  */
     571/** Parse MBR contents to mbr_part_t list */
    485572static int decode_logical(mbr_t * mbr, mbr_partitions_t * parts, mbr_part_t * ext)
    486573{
     
    496583
    497584
    498         uint32_t addr = ext->start_addr;
    499         //uint32_t base = ext->start_addr;
     585        uint32_t base = ext->start_addr;
     586        uint32_t addr = base;
    500587        br_block_t * ebr;
    501588
     
    503590        if (rc != EOK)
    504591                return rc;
    505 
    506         do {
     592       
     593        ebr = alloc_br();
     594        if (ebr == NULL) {
     595                rc = ENOMEM;
     596                goto end;
     597        }
     598
     599        rc = block_read_direct(mbr->device, addr, 1, ebr);
     600        if (rc != EOK) {
     601                goto free_ebr_end;
     602        }
     603
     604        if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
     605                rc = EINVAL;
     606                goto free_ebr_end;
     607        }
     608       
     609        if (ebr->pte[0].ptype == PT_UNUSED) {
     610                rc = EOK;
     611                goto free_ebr_end;
     612        }
     613       
     614        p = mbr_alloc_partition();
     615        if (p == NULL) {
     616                rc = ENOMEM;
     617                goto free_ebr_end;
     618        }
     619       
     620
     621        decode_part(&(ebr->pte[0]), p, base);
     622        mbr_set_flag(p, ST_LOGIC, true);
     623        p->ebr = ebr;
     624        mbr_add_partition(parts, p);
     625
     626        addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
     627       
     628        while (ebr->pte[1].ptype != PT_UNUSED) {
    507629                ebr = alloc_br();
    508630                if (ebr == NULL) {
    509                         return ENOMEM;
     631                        rc = ENOMEM;
     632                        goto end;
    510633                }
    511634
    512635                rc = block_read_direct(mbr->device, addr, 1, ebr);
    513636                if (rc != EOK) {
    514                         return rc;
    515                 }
    516 
    517                 //FIXME: is this the right way?
     637                        goto free_ebr_end;
     638                }
     639
    518640                if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) {
    519                         return EINVAL;
     641                        rc = EINVAL;
     642                        goto free_ebr_end;
    520643                }
    521644
    522645                p = mbr_alloc_partition();
    523 
    524                 decode_part(&(ebr->pte[0]), p, addr);
     646                if (p == NULL) {
     647                        rc = ENOMEM;
     648                        goto free_ebr_end;
     649                }
     650
     651                decode_part(&(ebr->pte[0]), p, base);
    525652                mbr_set_flag(p, ST_LOGIC, true);
    526653                p->ebr = ebr;
    527654                mbr_add_partition(parts, p);
    528655
    529                 //TODO: Check this code
    530                 addr = ebr->pte[1].first_lba + ext->start_addr;
    531         } while (ebr->pte[1].ptype != PT_UNUSED);
    532 
    533 
     656                addr = uint32_t_le2host(ebr->pte[1].first_lba) + base;
     657        }
     658       
     659        rc = EOK;
     660       
     661free_ebr_end:
     662        free(ebr);
     663       
     664end:
    534665        block_fini(mbr->device);
    535666
    536         return EOK;
     667        return rc;
    537668}
    538669
     
    543674                trgt->status = mbr_get_flag(src, ST_BOOT) ? B_ACTIVE : B_INACTIVE;
    544675                trgt->ptype = src->type;
    545                 trgt->first_lba = host2uint32_t_le(src->start_addr - base + 63); //63 sectors skipped
    546                 trgt->length = host2uint32_t_le(src->length - 64);      //63 + 1 (EBR)
     676                trgt->first_lba = host2uint32_t_le(src->start_addr - base);
     677                trgt->length = host2uint32_t_le(src->length);
    547678        } else {
    548679                trgt->status = 0;
Note: See TracChangeset for help on using the changeset viewer.