Changeset 8f6c7785 in mainline for uspace/lib/mbr/libmbr.c
- Timestamp:
- 2013-04-26T02:55:32Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 700f89e
- Parents:
- d617050
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
rd617050 r8f6c7785 33 33 */ 34 34 35 #include <async.h> 36 #include <assert.h> 37 #include <block.h> 38 #include <byteorder.h> 39 #include <errno.h> 35 40 #include <ipc/bd.h> 36 #include < async.h>41 #include <mem.h> 37 42 #include <stdio.h> 38 #include <block.h>39 #include <errno.h>40 43 #include <stdlib.h> 41 #include <assert.h>42 #include <byteorder.h>43 44 44 45 #include "libmbr.h" … … 47 48 static int decode_part(pt_entry_t * src, mbr_part_t * trgt, uint32_t base); 48 49 static int decode_logical(mbr_t * mbr, mbr_partitions_t * p, mbr_part_t * ext); 49 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base );50 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base, bool ebr); 50 51 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2); 51 52 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer); 52 53 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee); 54 55 static void debug_print(unsigned char * data, size_t bytes); 53 56 54 57 /** Read MBR from specific device … … 128 131 mbr_partitions_t * mbr_read_partitions(mbr_t * mbr) 129 132 { 130 int rc, i ;133 int rc, i, rc_ext; 131 134 mbr_part_t * p; 132 135 mbr_part_t * ext = NULL; 133 136 mbr_partitions_t * parts; 134 137 135 138 if (mbr == NULL) 136 139 return NULL; 137 140 138 141 parts = mbr_alloc_partitions(); 139 142 if (parts == NULL) { … … 145 148 if (mbr->raw_data.pte[i].ptype == PT_UNUSED) 146 149 continue; 147 148 p = malloc(sizeof(mbr_part_t)); 150 151 //p = malloc(sizeof(mbr_part_t)); 152 p = mbr_alloc_partition(); 149 153 if (p == NULL) { 150 154 printf(LIBMBR_NAME ": Error on memory allocation.\n"); 151 free(p);152 155 mbr_free_partitions(parts); 153 156 return NULL; 154 157 } 155 158 //list_append(&(p->link), &(parts->list)); 156 p->ebr = NULL; 157 if (decode_part(&(mbr->raw_data.pte[i]), p, 0)) { 159 rc_ext = decode_part(&(mbr->raw_data.pte[i]), p, 0); 160 mbr_set_flag(p, ST_LOGIC, false); 161 rc = mbr_add_partition(parts, p); 162 if (rc != ERR_OK) { 163 printf(LIBMBR_NAME ": Error occured during decoding the MBR. (%d)\n" \ 164 LIBMBR_NAME ": Partition list may be incomplete.\n", rc); 165 return NULL; 166 } 167 168 if (rc_ext) { 158 169 ext = p; 159 170 parts->l_extended = list_last(&(parts->list)); 160 171 } 161 mbr_set_flag(p, ST_LOGIC, false); 162 mbr_add_partition(parts, p); 163 } 164 172 } 173 165 174 // Fill in the primary partitions and generate logical ones, if any 166 175 rc = decode_logical(mbr, parts, ext); … … 169 178 LIBMBR_NAME ": Partition list may be incomplete.\n"); 170 179 } 171 180 181 //DEBUG: 182 //debug_print((unsigned char *) list_get_instance(list_last(&(parts->list)), mbr_part_t, link)->ebr, 512); 172 183 return parts; 173 184 } … … 188 199 mbr_part_t * ext = (parts->l_extended == NULL) ? NULL 189 200 : list_get_instance(parts->l_extended, mbr_part_t, link); 190 201 191 202 //br_block_t * last_ebr = NULL; 192 203 //link_t * it; 193 204 194 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); 195 206 196 207 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 197 208 if (rc != EOK) { … … 228 239 229 240 }*/ 230 241 231 242 link_t * l = parts->list.head.next; 232 243 233 244 // Encoding primary partitions 234 245 for (i = 0; i < parts->n_primary; i++) { 235 246 p = list_get_instance(l, mbr_part_t, link); 236 encode_part(p, &(mbr->raw_data.pte[i]), 0 );247 encode_part(p, &(mbr->raw_data.pte[i]), 0, false); 237 248 l = l->next; 238 249 } 239 250 240 251 // Writing MBR 241 252 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); … … 244 255 goto end; 245 256 } 246 257 247 258 if (ext == NULL) 248 259 goto no_extended; 249 250 260 261 //DEBUG: 262 //debug_print((unsigned char *) list_get_instance(list_last(&(parts->list)), mbr_part_t, link)->ebr, 512); 251 263 uint32_t base = ext->start_addr; 252 uint32_t addr = base; 253 264 //uint32_t addr = base; 265 //uint32_t prev_addr; 266 //mbr_part_t * tmp; 267 mbr_part_t * prev_p; 254 268 // Encoding and writing first logical partition 255 269 if (l != &(parts->list.head)) { 256 270 p = list_get_instance(l, mbr_part_t, link); 257 if (p->ebr == NULL) { 258 p->ebr = alloc_br(); 259 if (p->ebr == NULL) { 260 rc = ENOMEM; 261 goto end; 262 } 263 } 264 265 encode_part(p, &(p->ebr->pte[0]), base); 266 267 if (l->next == &(parts->list.head)) 268 encode_part(NULL, &(p->ebr->pte[1]), base); 269 else 270 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base); 271 272 271 p->ebr_addr = base; 272 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 273 285 rc = block_write_direct(dev_handle, base, 1, p->ebr); 274 286 if (rc != EOK) { 275 287 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 276 288 goto end; 277 } 278 289 }*/ 290 279 291 l = l->next; 280 } 281 282 283 292 } else 293 goto no_logical; 294 295 //prev_addr = base; 296 prev_p = p; 297 284 298 // Encoding and writing logical partitions 285 299 while (l != &(parts->list.head)) { 286 300 p = list_get_instance(l, mbr_part_t, link); 287 if (p->ebr == NULL) { 288 p->ebr = alloc_br(); 289 if (p->ebr == NULL) { 290 rc = ENOMEM; 291 goto end; 292 } 293 } 294 295 addr = p->start_addr - base; 296 encode_part(p, &(p->ebr->pte[0]), addr); 297 298 if (l->next == &(parts->list.head)) 299 encode_part(NULL, &(p->ebr->pte[1]), base); 301 302 /* Checking whether EBR address makes sense. If not, we take a guess. 303 * So far this is simple, we just take the first preceeding sector. 304 * Fdisk always reserves at least 2048 sectors (1MiB), so it can have 305 * the EBR aligned as well as the partition itself. Parted reserves 306 * minimum one sector, like we do. 307 * 308 * Note that we know there is at least one sector free from previous checks. 309 * Also note that the user can set ebr_addr to their liking (if it's valid). */ 310 if (p->ebr_addr >= p->start_addr || p->ebr_addr <= (prev_p->start_addr + prev_p->length)) { 311 p->ebr_addr = p->start_addr - 1; 312 DEBUG_PRINT_0(LIBMBR_NAME ": Warning: invalid EBR address.\n"); 313 } 314 315 encode_part(p, &(p->ebr->pte[0]), p->ebr_addr, false); 316 debug_print(((unsigned char*) p->ebr) + 446, 32); 317 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); 300 321 else 301 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base );302 303 304 rc = block_write_direct(dev_handle, addr, 1,p->ebr);322 encode_part(list_get_instance(l->next, mbr_part_t, link), &(p->ebr->pte[1]), base, true); 323 */ 324 325 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr); 305 326 if (rc != EOK) { 306 327 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 307 328 goto end; 308 329 } 309 330 331 prev_p = p; 310 332 l = l->next; 311 333 } 312 334 335 encode_part(NULL, &(prev_p->ebr->pte[1]), 0, false); 336 rc = block_write_direct(dev_handle, prev_p->ebr_addr, 1, prev_p->ebr); 337 if (rc != EOK) { 338 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 339 goto end; 340 } 341 342 no_logical: 313 343 no_extended: 314 344 315 345 /*if (ext == NULL) 316 346 goto no_extended; … … 514 544 p = p->next; 515 545 }*/ 516 546 517 547 rc = EOK; 518 548 519 549 end: 520 550 block_fini(dev_handle); 521 551 522 552 return rc; 523 553 } … … 536 566 p->start_addr = 0; 537 567 p->length = 0; 568 p->ebr_addr = 0; 538 569 539 570 return p; … … 561 592 int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p) 562 593 { 563 if (mbr_get_flag(p, ST_LOGIC)) { 564 // adding logical part 594 if (mbr_get_flag(p, ST_LOGIC)) { // adding logical part 565 595 if (parts->l_extended == NULL) { 566 596 return ERR_NO_EXTENDED; 567 597 } 568 if (!check_encaps(p, list_get_instance(parts->l_extended, mbr_part_t, link))) { 598 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); 569 602 return ERR_OUT_BOUNDS; 570 603 } 571 604 572 605 mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link); 606 mbr_part_t * iter; 607 uint32_t ebr_space = 1; 573 608 mbr_part_foreach(parts, iter) { 574 609 if (mbr_get_flag(iter, ST_LOGIC)) { 575 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); 576 613 return ERR_OVERLAP; 577 614 } 578 if (check_preceeds( p, iter)) {615 if (check_preceeds(iter, p)) { 579 616 last = iter; 617 ebr_space = p->start_addr - (last->start_addr + last->length); 618 } else 580 619 break; 581 }582 620 } 583 621 } 584 622 623 // checking if there's at least one sector of space preceeding 624 625 if (ebr_space < 1) 626 return ERR_NO_EBR; 627 628 // checking if there's at least one sector of space following (for following partitions's EBR) 629 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) { 631 return ERR_NO_EBR; 632 } 633 } 634 635 if (p->ebr == NULL) { 636 p->ebr = alloc_br(); 637 if (p->ebr == NULL) { 638 return ERR_NOMEM; 639 } 640 } 641 642 //printf("DEBUG: last: start: %u\n", last->start_addr); 585 643 //list_prepend(&(p->link), &(parts->list)); 586 list_insert_ before(&(p->link), &(last->link));644 list_insert_after(&(p->link), &(last->link)); 587 645 parts->n_logical += 1; 588 646 } else { … … 591 649 return ERR_PRIMARY_FULL; 592 650 } 651 652 // should we check if it's inside the drive's upper boundary? 653 if (p->start_addr == 0) { 654 return ERR_OUT_BOUNDS; 655 } 656 593 657 if (p->type == PT_EXTENDED && parts->l_extended != NULL) { 594 658 return ERR_EXTENDED_PRESENT; … … 598 662 list_append(&(p->link), &(parts->list)); 599 663 } else { 664 mbr_part_t * iter; 600 665 mbr_part_foreach(parts, iter) { 601 666 if (mbr_get_flag(iter, ST_LOGIC)) { 602 667 list_insert_before(&(p->link), &(iter->link)); 603 parts->n_primary += 1;604 668 break; 605 669 } else if (check_overlap(p, iter)) { … … 607 671 } 608 672 } 609 } 673 if (iter == list_get_instance(&(parts->list.head.prev), mbr_part_t, link)) { 674 list_append(&(p->link), &(parts->list)); 675 } 676 677 } 678 parts->n_primary += 1; 610 679 } 611 680 … … 663 732 } 664 733 734 /** Get next aligned address (in sectors!) */ 735 uint32_t mbr_get_next_aligned(uint32_t addr, unsigned int alignment) 736 { 737 uint32_t div = addr / alignment; 738 return (div + 1) * alignment; 739 } 740 665 741 /** Just a wrapper for free() */ 666 742 void mbr_free_mbr(mbr_t * mbr) … … 691 767 if (br == NULL) 692 768 return NULL; 693 769 770 memset(br, 0, 512); 694 771 br->media_id = 0; 695 772 br->pad0 = 0; 696 773 br->signature = host2uint16_t_le(BR_SIGNATURE); 697 774 698 775 return br; 699 776 } … … 733 810 uint32_t addr = base; 734 811 br_block_t * ebr; 735 812 736 813 rc = block_init(EXCHANGE_ATOMIC, mbr->device, 512); 737 814 if (rc != EOK) 738 815 return rc; 739 816 740 817 ebr = alloc_br(); 741 818 if (ebr == NULL) { … … 743 820 goto end; 744 821 } 745 822 746 823 rc = block_read_direct(mbr->device, addr, 1, ebr); 747 824 if (rc != EOK) { 748 825 goto free_ebr_end; 749 826 } 750 827 751 828 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 752 829 rc = EINVAL; 753 830 goto free_ebr_end; 754 831 } 755 832 756 833 if (ebr->pte[0].ptype == PT_UNUSED) { 757 834 rc = EOK; 758 835 goto free_ebr_end; 759 836 } 760 837 761 838 p = mbr_alloc_partition(); 762 839 if (p == NULL) { … … 764 841 goto free_ebr_end; 765 842 } 766 767 843 768 844 decode_part(&(ebr->pte[0]), p, base); 769 845 mbr_set_flag(p, ST_LOGIC, true); 770 846 p->ebr = ebr; 771 mbr_add_partition(parts, p); 772 847 p->ebr_addr = addr; 848 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); 852 return EINVAL; 853 } 854 773 855 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 774 856 printf("DEBUG: b: %u, a: %u, start: %u\n", base, addr, ebr->pte[1].first_lba); 857 775 858 while (ebr->pte[1].ptype != PT_UNUSED) { 776 859 ebr = alloc_br(); … … 779 862 goto end; 780 863 } 781 864 782 865 rc = block_read_direct(mbr->device, addr, 1, ebr); 783 866 if (rc != EOK) { 784 867 goto free_ebr_end; 785 868 } 786 869 787 870 if (uint16_t_le2host(ebr->signature) != BR_SIGNATURE) { 788 871 rc = EINVAL; 789 872 goto free_ebr_end; 790 873 } 791 874 792 875 p = mbr_alloc_partition(); 793 876 if (p == NULL) { … … 795 878 goto free_ebr_end; 796 879 } 797 798 decode_part(&(ebr->pte[0]), p, base); 880 881 //printf("DEBUG: b: %u, a: %u, start: %u\n", base, addr, ebr->pte[0].first_lba); 882 decode_part(&(ebr->pte[0]), p, addr); 799 883 mbr_set_flag(p, ST_LOGIC, true); 800 884 p->ebr = ebr; 801 mbr_add_partition(parts, p); 802 885 p->ebr_addr = addr; 886 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); 890 return EINVAL; 891 } 892 803 893 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 804 894 } 805 895 806 896 rc = EOK; 807 897 goto end; 898 808 899 free_ebr_end: 809 900 free(ebr); 810 901 811 902 end: 812 903 block_fini(mbr->device); 813 904 814 905 return rc; 815 906 } 816 907 817 908 /** Convert mbr_part_t to pt_entry_t */ 818 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base )909 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base, bool ebr) 819 910 { 820 911 if (src != NULL) { 821 912 trgt->status = mbr_get_flag(src, ST_BOOT) ? B_ACTIVE : B_INACTIVE; 822 trgt->ptype = src->type; 823 trgt->first_lba = host2uint32_t_le(src->start_addr - base); 824 trgt->length = host2uint32_t_le(src->length); 913 if (ebr) { // encoding reference to EBR 914 trgt->ptype = PT_EXTENDED_LBA; 915 trgt->first_lba = host2uint32_t_le(src->ebr_addr - base); 916 trgt->length = host2uint32_t_le(src->length + src->start_addr - src->ebr_addr); 917 } else { // encoding reference to partition 918 trgt->ptype = src->type; 919 trgt->first_lba = host2uint32_t_le(src->start_addr - base); 920 trgt->length = host2uint32_t_le(src->length); 921 } 825 922 } else { 826 923 trgt->status = 0; … … 839 936 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 840 937 { 841 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length < =p2->start_addr) {938 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length < p2->start_addr) { 842 939 return 0; 843 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length < =p1->start_addr) {940 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length < p1->start_addr) { 844 941 return 0; 845 942 } … … 864 961 } 865 962 866 867 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
Note:
See TracChangeset
for help on using the changeset viewer.