Changeset 700f89e in mainline for uspace/lib/mbr/libmbr.c
- Timestamp:
- 2013-05-02T00:51:28Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9bda5d90
- Parents:
- 8f6c7785
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
r8f6c7785 r700f89e 53 53 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee); 54 54 55 static void debug_print(unsigned char * data, size_t bytes); 55 /** Allocate memory for mbr_t */ 56 mbr_t * mbr_alloc_mbr() 57 { 58 return alloc_br(); 59 } 56 60 57 61 /** Read MBR from specific device … … 71 75 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 72 76 if (rc != EOK) { 77 free(mbr); 73 78 return NULL; 74 79 } … … 76 81 rc = block_read_direct(dev_handle, 0, 1, &(mbr->raw_data)); 77 82 if (rc != EOK) { 83 free(mbr); 78 84 block_fini(dev_handle); 79 85 return NULL; … … 83 89 84 90 mbr->device = dev_handle; 85 //mbr->partitions = NULL;86 91 87 92 return mbr; … … 93 98 * from the device in 'mbr') 94 99 * 95 * @return 0 on success, -1 on block_init error, -2 on write error100 * @return 0 on success, otherwise libblock error code 96 101 */ 97 102 int mbr_write_mbr(mbr_t * mbr, service_id_t dev_handle) … … 149 154 continue; 150 155 151 //p = malloc(sizeof(mbr_part_t));152 156 p = mbr_alloc_partition(); 153 157 if (p == NULL) { … … 156 160 return NULL; 157 161 } 158 //list_append(&(p->link), &(parts->list));162 159 163 rc_ext = decode_part(&(mbr->raw_data.pte[i]), p, 0); 160 164 mbr_set_flag(p, ST_LOGIC, false); … … 179 183 } 180 184 181 //DEBUG:182 //debug_print((unsigned char *) list_get_instance(list_last(&(parts->list)), mbr_part_t, link)->ebr, 512);183 185 return parts; 184 186 } … … 193 195 int mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle) 194 196 { 195 //bool logical = false;196 197 int i = 0; 197 198 int rc; … … 200 201 : list_get_instance(parts->l_extended, mbr_part_t, link); 201 202 202 //br_block_t * last_ebr = NULL;203 //link_t * it;204 205 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);206 207 203 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 208 204 if (rc != EOK) { 209 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d):%s.\n", rc, str_error(rc));205 printf(LIBMBR_NAME ": Error while initializing libblock: %d - %s.\n", rc, str_error(rc)); 210 206 return rc; 211 207 } 212 /*213 // Encoding primary partitions214 for (i = 0; i < parts->n_primary; i++) {215 encode_part(p, &(mbr->raw_data.pte[i]), 0);216 }217 218 // Writing MBR219 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));220 if (rc != EOK) {221 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));222 goto end;223 }224 225 uint32_t base = ext->start_addr;226 uint32_t addr = base;227 228 // Encoding and writing logical partitions229 mbr_part_foreach(parts, p) {230 if (p->ebr == NULL) {231 p->ebr = alloc_br();232 if (p->ebr == NULL)233 {234 rc = ENOMEM;235 goto end;236 }237 }238 239 240 }*/241 208 242 209 link_t * l = parts->list.head.next; … … 252 219 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); 253 220 if (rc != EOK) { 254 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d):%s.\n", rc, str_error(rc));221 printf(LIBMBR_NAME ": Error while writing MBR : %d - %s.\n", rc, str_error(rc)); 255 222 goto end; 256 223 } 257 224 258 225 if (ext == NULL) 259 goto no_extended; 260 261 //DEBUG: 262 //debug_print((unsigned char *) list_get_instance(list_last(&(parts->list)), mbr_part_t, link)->ebr, 512); 226 goto end; 227 263 228 uint32_t base = ext->start_addr; 264 //uint32_t addr = base;265 //uint32_t prev_addr;266 //mbr_part_t * tmp;267 229 mbr_part_t * prev_p; 230 231 /* Note for future changes: Some thought has been put into design 232 * and implementation. If you don't have to change it, don't. Other 233 * designs have been tried, this came out as the least horror with 234 * as much power over it as you can get. Thanks. */ 235 268 236 // Encoding and writing first logical partition 269 237 if (l != &(parts->list.head)) { … … 271 239 p->ebr_addr = base; 272 240 encode_part(p, &(p->ebr->pte[0]), base, false); 273 274 /*if (l->next == &(parts->list.head)) 275 encode_part(NULL, &(p->ebr->pte[1]), base, false); 276 else { 277 tmp = list_get_instance(l->next, mbr_part_t, link); 278 //debug_print((unsigned char*) p->ebr, 512); 279 printf("DEBUG: base: %u, tmp: start: %u, end: %u\n", base, tmp->start_addr, tmp->start_addr + tmp->length); 280 //encode_part(tmp, &(p->ebr->pte[1]), base); 281 encode_part(tmp, &(p->ebr->pte[1]), base, true); 282 debug_print(((unsigned char*) p->ebr) + 446, 32); 283 } 284 285 rc = block_write_direct(dev_handle, base, 1, p->ebr); 241 l = l->next; 242 } else { 243 /* If there was an extended but no logical, we should overwrite 244 * the space where the first logical's EBR would have been. There 245 * might be some garbage from the past. */ 246 br_block_t * tmp = alloc_br(); 247 rc = block_write_direct(dev_handle, base, 1, tmp); 286 248 if (rc != EOK) { 287 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d):%s.\n", rc, str_error(rc));249 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc)); 288 250 goto end; 289 }*/ 290 291 l = l->next; 292 } else 293 goto no_logical; 294 295 //prev_addr = base; 251 } 252 free(tmp); 253 goto end; 254 } 255 296 256 prev_p = p; 297 257 … … 314 274 315 275 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false); 316 debug_print(((unsigned char*) p->ebr) + 446, 32);317 276 encode_part(p, &(prev_p->ebr->pte[1]), base, true); 318 debug_print(((unsigned char*) prev_p->ebr) + 446, 32);319 /*if (l->next == &(parts->list.head))320 encode_part(NULL, &(p->ebr->pte[1]), base, false);321 else322 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base, true);323 */324 277 325 278 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr); 326 279 if (rc != EOK) { 327 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d):%s.\n", rc, str_error(rc));280 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc)); 328 281 goto end; 329 282 } … … 333 286 } 334 287 288 // write the last EBR 335 289 encode_part(NULL, &(prev_p->ebr->pte[1]), 0, false); 336 290 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr); 337 291 if (rc != EOK) { 338 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d):%s.\n", rc, str_error(rc));292 printf(LIBMBR_NAME ": Error while writing EBR: %d - %s.\n", rc, str_error(rc)); 339 293 goto end; 340 294 } 341 342 no_logical:343 no_extended:344 345 /*if (ext == NULL)346 goto no_extended;347 348 uint32_t base = ext->start_addr;349 uint32_t addr;// = base;350 uint32_t prev_addr;351 mbr_part_t * prev_part = NULL;352 353 list_foreach(parts->list, iter) {354 p = list_get_instance(iter, mbr_part_t, link);355 if (mbr_get_flag(p, ST_LOGIC)) {356 // writing logical partition357 logical = true;358 359 if (p->ebr == NULL) {360 p->ebr = alloc_br();361 if (p->ebr == NULL)362 {363 rc = ENOMEM;364 goto end;365 }366 }367 368 if (prev_part != NULL) {369 // addr is the address of EBR370 addr = p->start_addr - base;371 // base-1 means start_lba+1372 encode_part(p, &(p->ebr->pte[0]), addr - 1);373 encode_part(p, &(prev_part->ebr->pte[1]), base);374 rc = block_write_direct(dev_handle, prev_addr, 1, prev_part->ebr);375 if (rc != EOK) {376 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));377 goto end;378 }379 } else {380 // addr is the address of EBR381 addr = base;382 // base-1 means start_lba+1383 // Fixed: mbr_add_partition now performs checks!nevim384 encode_part(p, &(p->ebr->pte[0]), base);385 }386 387 //addr = p->start_addr;388 prev_addr = addr;389 prev_part = p;390 } else {391 // writing primary partition392 if (i >= 4) {393 rc = EINVAL;394 goto end;395 }396 397 encode_part(p, &(mbr->raw_data.pte[i]), 0);398 399 ++i;400 }401 } //*/402 403 /* If there was an extended but no logical, we should overwrite404 * the space where the first logical's EBR would have been. There405 * might be some garbage from the past.406 */407 /*408 last_ebr = prev_part->ebr;409 410 if (!logical)411 {412 last_ebr = alloc_br();413 if (last_ebr == NULL) {414 rc = ENOMEM;415 goto end;416 }417 418 last_ebr->pte[0].ptype = PT_UNUSED;419 }420 421 422 encode_part(NULL, &(last_ebr->pte[1]), 0);423 rc = block_write_direct(dev_handle, addr, 1, last_ebr);424 425 if (!logical)426 {427 free(last_ebr);428 }429 */430 /*431 if (rc != EOK) {432 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));433 goto end;434 }435 436 goto skip;437 438 no_extended:439 */440 /*list_foreach(parts->list, it) {441 p = list_get_instance(it, mbr_part_t, link);442 if (mbr_get_flag(p, ST_LOGIC)) {443 // extended does not exist, fail444 return EINVAL;445 } else {446 // writing primary partition447 if (i >= 4)448 return EINVAL;449 450 encode_part(p, &(mbr->raw_data.pte[i]), 0);451 452 ++i;453 }454 }*/455 /*456 it = parts->list.head.next;457 for (i = 0; i < N_PRIMARY; i++) {458 if (it != &parts->list.head) {459 p = list_get_instance(it, mbr_part_t, link);460 if (mbr_get_flag(p, ST_LOGIC)) {461 // extended does not exist, fail462 return EINVAL;463 } else {464 // writing primary partition465 if (i >= 4)466 return EINVAL;467 468 encode_part(p, &(mbr->raw_data.pte[i]), 0);469 470 }471 472 it = it->next;473 } else {474 encode_part(NULL, &(mbr->raw_data.pte[i]), 0);475 }476 }477 478 479 skip:480 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));481 if (rc != EOK) {482 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc));483 goto end;484 }485 */486 487 /*488 for (i = 0; i < N_PRIMARY; ++i) {489 encode_part(&(p->partition), &(mbr->raw_data.pte[i]), 0);490 if (p->type == PT_EXTENDED)491 ext = p;492 493 //p = list_get_instance(p->link.next, mbr_partitions_t, link);494 p = p->next;495 }496 497 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data));498 if (rc != EOK) {499 block_fini(dev_handle);500 return rc;501 }502 503 //writing logical partitions504 505 if (p == NULL && ext != NULL) {506 //we need an empty EBR to rewrite the old EBR on disk, if we need to delete it507 br_block_t * temp_ebr = alloc_br();508 if (temp_ebr == NULL) {509 block_fini(dev_handle);510 return ENOMEM;511 }512 513 temp_ebr->pte[0].ptype = PT_UNUSED;514 encode_part(NULL, &(temp_ebr->pte[1]), 0);515 rc = block_write_direct(dev_handle, ext->start_addr, 1, temp_ebr);516 free(temp_ebr);517 block_fini(dev_handle);518 return rc;519 }520 521 if (p != NULL && ext == NULL) {522 block_fini(dev_handle);523 //no extended but one or more logical? EINVAL to the rescue!524 return EINVAL;525 }526 527 aoff64_t addr = ext->start_addr;528 529 while (p != NULL) {530 if (p->type == PT_UNUSED) {531 p = p->next;532 continue;533 }534 //encode_part(p, &(p->ebr->pte[0]), p->start_addr - 63 * 512);535 encode_part(p, &(p->ebr->pte[0]), addr);536 encode_part(p->next, &(p->ebr->pte[1]), ext->start_addr);537 538 rc = block_write_direct(dev_handle, p->start_addr, 1, p->ebr);539 if (rc != EOK) {540 block_fini(dev_handle);541 return rc;542 }543 addr = p->start_addr;544 p = p->next;545 }*/546 295 547 296 rc = EOK; … … 560 309 return NULL; 561 310 } 311 562 312 link_initialize(&(p->link)); 563 313 p->ebr = NULL; … … 571 321 } 572 322 323 /** mbr_partitions_t constructor */ 573 324 mbr_partitions_t * mbr_alloc_partitions(void) 574 325 { … … 579 330 580 331 list_initialize(&(parts->list)); 581 582 332 parts->n_primary = 0; 583 333 parts->n_logical = 0; … … 589 339 /** Add partition 590 340 * Performs checks, sorts the list. 591 */ 592 int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p) 341 * 342 * @param parts partition list to add to 343 * @param p partition to add 344 * 345 * @return ERR_OK (0) on success, other MBR_ERR_VAL otherwise 346 */ 347 MBR_ERR_VAL mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p) 593 348 { 594 349 if (mbr_get_flag(p, ST_LOGIC)) { // adding logical part 595 if (parts->l_extended == NULL) { 350 // is there any extended partition? 351 if (parts->l_extended == NULL) 596 352 return ERR_NO_EXTENDED; 597 } 353 354 // is the logical partition inside the extended one? 598 355 mbr_part_t * ext = list_get_instance(parts->l_extended, mbr_part_t, link); 599 if (!check_encaps(p, ext)) { 600 //printf("DEBUG: OOB: start: %u, end: %u\n", h->start_addr, h->start_addr + h->length); 601 //printf("DEBUG: OOB: start: %u, end: %u\n", p->start_addr, p->start_addr + p->length); 356 if (!check_encaps(p, ext)) 602 357 return ERR_OUT_BOUNDS; 603 }604 358 359 // find a place for the new partition in a sorted linked list 605 360 mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link); 606 361 mbr_part_t * iter; … … 608 363 mbr_part_foreach(parts, iter) { 609 364 if (mbr_get_flag(iter, ST_LOGIC)) { 610 if (check_overlap(p, iter)) { 611 //printf("DEBUG: overlap: start: %u, end: %u\n", iter->start_addr, iter->start_addr + iter->length); 612 //printf("DEBUG: overlap: start: %u, end: %u\n", p->start_addr, p->start_addr + p->length); 365 if (check_overlap(p, iter)) 613 366 return ERR_OVERLAP; 614 }615 367 if (check_preceeds(iter, p)) { 616 368 last = iter; … … 622 374 623 375 // checking if there's at least one sector of space preceeding 624 625 376 if (ebr_space < 1) 626 377 return ERR_NO_EBR; … … 628 379 // checking if there's at least one sector of space following (for following partitions's EBR) 629 380 if (last->link.next != &(parts->list.head)) { 630 if (list_get_instance(&(last->link.next), mbr_part_t, link)->start_addr <= p->start_addr + p->length + 1) {381 if (list_get_instance(&(last->link.next), mbr_part_t, link)->start_addr <= p->start_addr + p->length + 1) 631 382 return ERR_NO_EBR; 632 633 }634 383 } 384 385 // alloc EBR if it's not already there 635 386 if (p->ebr == NULL) { 636 387 p->ebr = alloc_br(); … … 640 391 } 641 392 642 //printf("DEBUG: last: start: %u\n", last->start_addr); 643 //list_prepend(&(p->link), &(parts->list)); 393 // add it 644 394 list_insert_after(&(p->link), &(last->link)); 645 395 parts->n_logical += 1; 646 } else { 647 // adding primary 396 } else { // adding primary 648 397 if (parts->n_primary == 4) { 649 398 return ERR_PRIMARY_FULL; 650 399 } 651 400 652 // should we check if it's inside the drive's upper boundary?401 // TODO: should we check if it's inside the drive's upper boundary? 653 402 if (p->start_addr == 0) { 654 403 return ERR_OUT_BOUNDS; 655 404 } 656 405 406 // if it's extended, is there any other one? 657 407 if (p->type == PT_EXTENDED && parts->l_extended != NULL) { 658 408 return ERR_EXTENDED_PRESENT; 659 409 } 660 410 411 // find a place and add it 661 412 if (list_empty(&(parts->list))) { 662 413 list_append(&(p->link), &(parts->list)); … … 667 418 list_insert_before(&(p->link), &(iter->link)); 668 419 break; 669 } else if (check_overlap(p, iter)) {420 } else if (check_overlap(p, iter)) 670 421 return ERR_OVERLAP; 671 }672 422 } 673 if (iter == list_get_instance(&(parts->list.head.prev), mbr_part_t, link)) {423 if (iter == list_get_instance(&(parts->list.head.prev), mbr_part_t, link)) 674 424 list_append(&(p->link), &(parts->list)); 425 } 426 parts->n_primary += 1; 427 } 428 429 return ERR_OK; 430 } 431 432 /** Remove partition 433 * Removes partition by index, indexed from zero. When removing extended 434 * partition, all logical partitions get removed as well. 435 * 436 * @param parts partition list to remove from 437 * @param idx index of the partition to remove 438 * 439 * @return EOK on success, EINVAL if idx invalid 440 */ 441 int mbr_remove_partition(mbr_partitions_t * parts, size_t idx) 442 { 443 link_t * l = list_nth(&(parts->list), idx); 444 if (l == NULL) 445 return EINVAL; 446 447 mbr_part_t * p; 448 449 /* TODO: if it is extended partition, should we also remove all logical? 450 * If we don't, we break the consistency of the list. If we do, 451 * the user will have to input them all over again. So yes. */ 452 if (l == parts->l_extended) { 453 parts->l_extended = NULL; 454 455 link_t * it = l->next; 456 link_t * next_it; 457 while (it != &(parts->list.head)) { 458 next_it = it->next; 459 460 p = list_get_instance(it, mbr_part_t, link); 461 if (mbr_get_flag(p, ST_LOGIC)) { 462 list_remove(it); 463 parts->n_logical -= 1; 464 mbr_free_partition(p); 675 465 } 676 466 677 } 678 parts->n_primary += 1; 679 } 680 681 return ERR_OK; 682 } 683 684 /** Remove partition */ 685 int mbr_remove_partition(mbr_partitions_t * parts, size_t idx) 686 { 687 DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %zu\n", idx); 688 link_t * l = list_nth(&(parts->list), idx); 689 if (l == parts->l_extended) { 690 DEBUG_PRINT_0(LIBMBR_NAME "Removing extended partition.\n"); 691 parts->l_extended = NULL; 692 } 467 it = next_it; 468 } 469 470 } 471 693 472 list_remove(l); 694 mbr_part_t * p = list_get_instance(l, mbr_part_t, link); 695 if (mbr_get_flag(p, ST_LOGIC)) { 473 474 p = list_get_instance(l, mbr_part_t, link); 475 if (mbr_get_flag(p, ST_LOGIC)) 696 476 parts->n_logical -= 1; 697 } else {477 else 698 478 parts->n_primary -= 1; 699 } 700 701 479 480 702 481 mbr_free_partition(p); 703 482 704 483 return EOK; 705 484 } … … 769 548 770 549 memset(br, 0, 512); 771 br->media_id = 0;772 br->pad0 = 0;773 550 br->signature = host2uint16_t_le(BR_SIGNATURE); 774 551 … … 847 624 p->ebr_addr = addr; 848 625 rc = mbr_add_partition(parts, p); 849 if (rc != ERR_OK) { 850 printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \ 851 LIBMBR_NAME ": Partition list may be incomplete.\n", rc); 626 if (rc != ERR_OK) 852 627 return EINVAL; 853 }854 628 855 629 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 856 printf("DEBUG: b: %u, a: %u, start: %u\n", base, addr, ebr->pte[1].first_lba);857 630 858 631 while (ebr->pte[1].ptype != PT_UNUSED) { … … 879 652 } 880 653 881 //printf("DEBUG: b: %u, a: %u, start: %u\n", base, addr, ebr->pte[0].first_lba);654 882 655 decode_part(&(ebr->pte[0]), p, addr); 883 656 mbr_set_flag(p, ST_LOGIC, true); … … 885 658 p->ebr_addr = addr; 886 659 rc = mbr_add_partition(parts, p); 887 if (rc != ERR_OK) { 888 printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \ 889 LIBMBR_NAME ": Partition list may be incomplete.\n", rc); 660 if (rc != ERR_OK) 890 661 return EINVAL; 891 }892 662 893 663 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; … … 934 704 } 935 705 706 /** Check whether two partitions overlap 707 * 708 * @return 1 for yes, 0 for no 709 */ 936 710 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 937 711 { … … 945 719 } 946 720 721 /** Check whether one partition encapsulates the other 722 * 723 * @return 1 for yes, 0 for no 724 */ 947 725 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer) 948 726 { … … 956 734 } 957 735 736 /** Check whether one partition preceeds the other 737 * 738 * @return 1 for yes, 0 for no 739 */ 958 740 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee) 959 741 { … … 961 743 } 962 744 963 static void debug_print(unsigned char * data, size_t bytes) 964 { 965 size_t addr = 0; 966 int i; 967 968 while (bytes >= 16) { 969 printf("%8x ", addr); 970 for (i = 0; i < 8; i++) { 971 printf(" %2hhx", data[addr + i]); 972 } 973 printf(" "); 974 for (i = 0; i < 8; i++) { 975 printf(" %2hhx", data[addr + i + 8]); 976 } 977 printf("\n"); 978 979 bytes -= 16; 980 addr += 16; 981 } 982 983 984 } 985 986 987 745 746 747
Note:
See TracChangeset
for help on using the changeset viewer.