Changeset 6317b33 in mainline for uspace/lib/mbr/libmbr.c
- Timestamp:
- 2013-06-25T00:29:00Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 52f2c89
- Parents:
- cb328ab (diff), 1c8bfe8 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
rcb328ab r6317b33 52 52 static int check_encaps(mbr_part_t *, mbr_part_t *); 53 53 static 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); 54 56 55 57 /** Allocate and initialize mbr_label_t structure */ … … 168 170 mbr_part_t *ext = NULL; 169 171 //mbr_partitions_t *parts; 170 printf("check\n");172 171 173 if (label->parts != NULL) 172 174 mbr_free_partitions(label->parts); 173 printf("check2\n");175 174 176 label->parts = mbr_alloc_partitions(); 175 177 if (label->parts == NULL) { 176 178 return ENOMEM; 177 179 } 178 printf("primary\n");180 179 181 /* Generate the primary partitions */ 180 182 for (i = 0; i < N_PRIMARY; ++i) { 181 183 if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED) 182 184 continue; 183 printf("pcheck1\n");185 184 186 p = mbr_alloc_partition(); 185 187 if (p == NULL) { … … 188 190 return ENOMEM; 189 191 } 190 printf("pcheck2\n");192 191 193 rc_ext = decode_part(&(label->mbr->raw_data.pte[i]), p, 0); 192 194 mbr_set_flag(p, ST_LOGIC, false); … … 198 200 return EINVAL; 199 201 } 200 printf("pcheck3\n");202 201 203 if (rc_ext) { 202 204 ext = p; 203 label->parts->l_extended = list_nth(&(label->parts->list), i); 204 } 205 printf("pcheck4\n"); 206 } 207 printf("logical\n"); 205 label->parts->l_extended = &p->link; 206 } 207 } 208 208 209 /* Fill in the primary partitions and generate logical ones, if any */ 209 210 rc = decode_logical(label, ext); 210 211 if (rc != EOK) { 211 printf(LIBMBR_NAME ": Error occured during decoding the MBR.\n" \212 LIBMBR_NAME ": Partition list may be incomplete.\n" );212 printf(LIBMBR_NAME ": Error during decoding logical partitions: %d - %s.\n" \ 213 LIBMBR_NAME ": Partition list may be incomplete.\n", rc, str_error(rc)); 213 214 return rc; 214 215 } 215 printf("finish\n");216 216 217 return EOK; 217 218 } … … 225 226 int mbr_write_partitions(mbr_label_t *label, service_id_t dev_handle) 226 227 { 228 if (label->parts == NULL) 229 return EOK; 230 231 if (label->mbr == NULL) 232 label->mbr = mbr_alloc_mbr(); 233 227 234 int i = 0; 228 235 int rc; … … 240 247 241 248 /* Encoding primary partitions */ 242 for (i = 0; i < label->parts->n_primary; i++) {249 for (i = 0; i < N_PRIMARY; i++) { 243 250 p = list_get_instance(l, mbr_part_t, link); 244 251 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false); … … 253 260 } 254 261 255 if (ext == NULL) 262 if (ext == NULL) { 263 rc = EOK; 256 264 goto end; 265 } 257 266 258 267 uint32_t base = ext->start_addr; 259 mbr_part_t * 268 mbr_part_t *prev_p; 260 269 261 270 /* Note for future changes: Some thought has been put into design … … 281 290 } 282 291 free(tmp); 292 rc = EOK; 283 293 goto end; 284 294 } 285 295 286 296 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); 287 332 288 333 /* Encoding and writing logical partitions */ … … 290 335 p = list_get_instance(l, mbr_part_t, link); 291 336 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 have295 * the EBR aligned as well as the partition itself. Parted reserves296 * 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 }304 337 305 338 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false); … … 390 423 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p) 391 424 { 392 int rc; 393 mbr_partitions_t *parts = label->parts; 394 425 int rc1, rc2; 395 426 aoff64_t nblocks; 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));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)); 400 431 return ERR_LIBBLOCK; 401 432 } 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)); 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)); 407 441 return ERR_LIBBLOCK; 408 442 } 409 printf("add3.\n"); 410 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)) 411 454 /* adding logical partition */ 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 { 455 return mbr_add_logical(label, p); 456 else 454 457 /* adding primary */ 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; 458 return mbr_add_primary(label, p); 495 459 } 496 460 … … 569 533 void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value) 570 534 { 571 uint 8_t status = p->status;535 uint16_t status = p->status; 572 536 573 537 if (value) … … 579 543 } 580 544 581 /** Get next aligned address (in sectors!)*/545 /** Get next aligned address */ 582 546 uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment) 583 547 { 584 548 uint32_t div = addr / alignment; 585 549 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; 586 576 } 587 577 … … 627 617 trgt->type = src->ptype; 628 618 629 /* Checking only 0x80; otherwise writing will fix to 0x00 */ 630 trgt->status = (trgt->status & 0xFF00) | src->status; 619 trgt->status = (trgt->status & 0xFF00) | (uint16_t) src->status; 631 620 632 621 trgt->start_addr = uint32_t_le2host(src->first_lba) + base; … … 691 680 692 681 while (ebr->pte[1].ptype != PT_UNUSED) { 682 693 683 ebr = alloc_br(); 694 684 if (ebr == NULL) { … … 712 702 goto free_ebr_end; 713 703 } 714 715 704 716 705 decode_part(&(ebr->pte[0]), p, addr); … … 759 748 trgt->length = host2uint32_t_le(src->length); 760 749 } 750 751 if (trgt->ptype == PT_UNUSED) 752 memset(trgt, 0, sizeof(pt_entry_t)); 761 753 } else { 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; 754 memset(trgt, 0, sizeof(pt_entry_t)); 772 755 } 773 756 } … … 779 762 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 780 763 { 781 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) { 782 765 return 0; 783 } 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) { 784 767 return 0; 785 768 } … … 812 795 } 813 796 814 815 816 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
Note:
See TracChangeset
for help on using the changeset viewer.