Changeset 6e8e4e19 in mainline for uspace/lib/mbr/libmbr.c
- Timestamp:
- 2013-06-16T14:50:59Z (11 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1c8bfe8
- Parents:
- c9f61150
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
rc9f61150 r6e8e4e19 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 */ … … 171 173 mbr_part_t *ext = NULL; 172 174 //mbr_partitions_t *parts; 173 printf("check\n");175 174 176 if (label->parts != NULL) 175 177 mbr_free_partitions(label->parts); 176 printf("check2\n");178 177 179 label->parts = mbr_alloc_partitions(); 178 180 if (label->parts == NULL) { 179 181 return ENOMEM; 180 182 } 181 printf("primary\n");183 182 184 /* Generate the primary partitions */ 183 185 for (i = 0; i < N_PRIMARY; ++i) { 184 186 if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED) 185 187 continue; 186 printf("pcheck1\n");188 187 189 p = mbr_alloc_partition(); 188 190 if (p == NULL) { … … 191 193 return ENOMEM; 192 194 } 193 printf("pcheck2\n");195 194 196 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); 195 198 mbr_set_flag(p, ST_LOGIC, false); 196 199 rc = mbr_add_partition(label, p); … … 201 204 return EINVAL; 202 205 } 203 printf("pcheck3\n");206 204 207 if (rc_ext) { 205 208 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 211 214 /* Fill in the primary partitions and generate logical ones, if any */ 212 215 rc = decode_logical(label, ext); 213 216 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)); 216 219 return rc; 217 220 } 218 printf("finish\n");221 219 222 return EOK; 220 223 } … … 243 246 244 247 /* Encoding primary partitions */ 245 for (i = 0; i < label->parts->n_primary; i++) {248 for (i = 0; i < N_PRIMARY; i++) { 246 249 p = list_get_instance(l, mbr_part_t, link); 250 printf("status: %hu\n", p->status); 247 251 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false); 248 252 l = l->next; … … 256 260 } 257 261 258 if (ext == NULL) 262 if (ext == NULL) { 263 rc = EOK; 259 264 goto end; 265 } 260 266 261 267 uint32_t base = ext->start_addr; 262 mbr_part_t * 268 mbr_part_t *prev_p; 263 269 264 270 /* Note for future changes: Some thought has been put into design … … 284 290 } 285 291 free(tmp); 292 rc = EOK; 286 293 goto end; 287 294 } 288 295 289 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); 290 332 291 333 /* Encoding and writing logical partitions */ … … 293 335 p = list_get_instance(l, mbr_part_t, link); 294 336 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 have298 * the EBR aligned as well as the partition itself. Parted reserves299 * 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 }307 337 308 338 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false); … … 393 423 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p) 394 424 { 395 int rc; 396 mbr_partitions_t *parts = label->parts; 397 425 int rc1, rc2; 398 426 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)); 403 431 return ERR_LIBBLOCK; 404 432 } 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)); 410 441 return ERR_LIBBLOCK; 411 442 } 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)) 414 454 /* 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 457 457 /* 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); 498 459 } 499 460 … … 572 533 void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value) 573 534 { 574 uint 8_t status = p->status;535 uint16_t status = p->status; 575 536 576 537 if (value) … … 582 543 } 583 544 584 /** Get next aligned address (in sectors!)*/545 /** Get next aligned address */ 585 546 uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment) 586 547 { 587 548 uint32_t div = addr / alignment; 588 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; 589 576 } 590 577 … … 630 617 trgt->type = src->ptype; 631 618 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; 634 620 635 621 trgt->start_addr = uint32_t_le2host(src->first_lba) + base; … … 694 680 695 681 while (ebr->pte[1].ptype != PT_UNUSED) { 682 696 683 ebr = alloc_br(); 697 684 if (ebr == NULL) { … … 715 702 goto free_ebr_end; 716 703 } 717 718 704 719 705 decode_part(&(ebr->pte[0]), p, addr); … … 762 748 trgt->length = host2uint32_t_le(src->length); 763 749 } 750 751 if (trgt->ptype == PT_UNUSED) 752 memset(trgt, 0, sizeof(pt_entry_t)); 764 753 } 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)); 775 755 } 776 756 } … … 782 762 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 783 763 { 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) { 785 765 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) { 787 767 return 0; 788 768 } … … 815 795 } 816 796 817 818 819 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.