Changes in uspace/lib/mbr/libmbr.c [6e8e4e19:44c4886] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
r6e8e4e19 r44c4886 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);56 54 57 55 /** Allocate and initialize mbr_label_t structure */ … … 94 92 */ 95 93 int mbr_read_mbr(mbr_label_t *label, service_id_t dev_handle) 96 { 97 if (label == NULL) 98 return EINVAL; 99 94 { 100 95 int rc; 101 96 … … 173 168 mbr_part_t *ext = NULL; 174 169 //mbr_partitions_t *parts; 175 170 printf("check\n"); 176 171 if (label->parts != NULL) 177 172 mbr_free_partitions(label->parts); 178 173 printf("check2\n"); 179 174 label->parts = mbr_alloc_partitions(); 180 175 if (label->parts == NULL) { 181 176 return ENOMEM; 182 177 } 183 178 printf("primary\n"); 184 179 /* Generate the primary partitions */ 185 180 for (i = 0; i < N_PRIMARY; ++i) { 186 181 if (label->mbr->raw_data.pte[i].ptype == PT_UNUSED) 187 182 continue; 188 183 printf("pcheck1\n"); 189 184 p = mbr_alloc_partition(); 190 185 if (p == NULL) { … … 193 188 return ENOMEM; 194 189 } 195 190 printf("pcheck2\n"); 196 191 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);198 192 mbr_set_flag(p, ST_LOGIC, false); 199 193 rc = mbr_add_partition(label, p); … … 204 198 return EINVAL; 205 199 } 206 200 printf("pcheck3\n"); 207 201 if (rc_ext) { 208 202 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"); 214 208 /* Fill in the primary partitions and generate logical ones, if any */ 215 209 rc = decode_logical(label, ext); 216 210 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"); 219 213 return rc; 220 214 } 221 215 printf("finish\n"); 222 216 return EOK; 223 217 } … … 246 240 247 241 /* Encoding primary partitions */ 248 for (i = 0; i < N_PRIMARY; i++) {242 for (i = 0; i < label->parts->n_primary; i++) { 249 243 p = list_get_instance(l, mbr_part_t, link); 250 printf("status: %hu\n", p->status);251 244 encode_part(p, &(label->mbr->raw_data.pte[i]), 0, false); 252 245 l = l->next; … … 260 253 } 261 254 262 if (ext == NULL) { 263 rc = EOK; 255 if (ext == NULL) 264 256 goto end; 265 }266 257 267 258 uint32_t base = ext->start_addr; 268 mbr_part_t * prev_p;259 mbr_part_t * prev_p; 269 260 270 261 /* Note for future changes: Some thought has been put into design … … 290 281 } 291 282 free(tmp); 292 rc = EOK;293 283 goto end; 294 284 } 295 285 296 286 prev_p = p; 297 298 /* Check EBR addresses299 * This piece of code saves previous EBR placements from other300 * 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 have315 * the EBR aligned as well as the partition itself. Parted reserves316 * 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);332 287 333 288 /* Encoding and writing logical partitions */ … … 335 290 p = list_get_instance(l, mbr_part_t, link); 336 291 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 } 337 304 338 305 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false); … … 423 390 mbr_err_val mbr_add_partition(mbr_label_t *label, mbr_part_t *p) 424 391 { 425 int rc1, rc2; 392 int rc; 393 mbr_partitions_t *parts = label->parts; 394 426 395 aoff64_t nblocks; 427 428 rc 1= block_init(EXCHANGE_ATOMIC, label->device, 512);429 if (rc 1 != 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)); 431 400 return ERR_LIBBLOCK; 432 401 } 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)); 441 407 return ERR_LIBBLOCK; 442 408 } 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)) { 454 411 /* 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 { 457 454 /* 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; 459 495 } 460 496 … … 533 569 void mbr_set_flag(mbr_part_t *p, MBR_FLAGS flag, bool value) 534 570 { 535 uint 16_t status = p->status;571 uint8_t status = p->status; 536 572 537 573 if (value) … … 543 579 } 544 580 545 /** Get next aligned address */581 /** Get next aligned address (in sectors!) */ 546 582 uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment) 547 583 { 548 584 uint32_t div = addr / alignment; 549 585 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 else557 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 else566 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 else575 return NULL;576 586 } 577 587 … … 617 627 trgt->type = src->ptype; 618 628 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; 620 631 621 632 trgt->start_addr = uint32_t_le2host(src->first_lba) + base; … … 680 691 681 692 while (ebr->pte[1].ptype != PT_UNUSED) { 682 683 693 ebr = alloc_br(); 684 694 if (ebr == NULL) { … … 702 712 goto free_ebr_end; 703 713 } 714 704 715 705 716 decode_part(&(ebr->pte[0]), p, addr); … … 748 759 trgt->length = host2uint32_t_le(src->length); 749 760 } 750 751 if (trgt->ptype == PT_UNUSED)752 memset(trgt, 0, sizeof(pt_entry_t));753 761 } 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; 755 772 } 756 773 } … … 762 779 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 763 780 { 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) { 765 782 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) { 767 784 return 0; 768 785 } … … 795 812 } 796 813 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.