Changeset d617050 in mainline for uspace/lib/mbr
- Timestamp:
- 2013-04-20T01:13:44Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8f6c7785
- Parents:
- e91d17a
- Location:
- uspace/lib/mbr
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/mbr/libmbr.c
re91d17a rd617050 48 48 static int decode_logical(mbr_t * mbr, mbr_partitions_t * p, mbr_part_t * ext); 49 49 static void encode_part(mbr_part_t * src, pt_entry_t * trgt, uint32_t base); 50 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2); 51 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer); 52 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee); 50 53 51 54 /** Read MBR from specific device … … 142 145 if (mbr->raw_data.pte[i].ptype == PT_UNUSED) 143 146 continue; 144 147 145 148 p = malloc(sizeof(mbr_part_t)); 146 149 if (p == NULL) { … … 179 182 int mbr_write_partitions(mbr_partitions_t * parts, mbr_t * mbr, service_id_t dev_handle) 180 183 { 181 bool logical = false;184 //bool logical = false; 182 185 int i = 0; 183 186 int rc; … … 185 188 mbr_part_t * ext = (parts->l_extended == NULL) ? NULL 186 189 : list_get_instance(parts->l_extended, mbr_part_t, link); 187 188 br_block_t * last_ebr = NULL;189 link_t * it;190 190 191 //br_block_t * last_ebr = NULL; 192 //link_t * it; 193 191 194 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); 192 195 193 196 rc = block_init(EXCHANGE_ATOMIC, dev_handle, 512); 194 197 if (rc != EOK) { … … 196 199 return rc; 197 200 } 201 /* 202 // Encoding primary partitions 203 for (i = 0; i < parts->n_primary; i++) { 204 encode_part(p, &(mbr->raw_data.pte[i]), 0); 205 } 206 207 // Writing MBR 208 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); 209 if (rc != EOK) { 210 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 211 goto end; 212 } 213 214 uint32_t base = ext->start_addr; 215 uint32_t addr = base; 216 217 // Encoding and writing logical partitions 218 mbr_part_foreach(parts, p) { 219 if (p->ebr == NULL) { 220 p->ebr = alloc_br(); 221 if (p->ebr == NULL) 222 { 223 rc = ENOMEM; 224 goto end; 225 } 226 } 227 228 229 }*/ 230 231 link_t * l = parts->list.head.next; 232 233 // Encoding primary partitions 234 for (i = 0; i < parts->n_primary; i++) { 235 p = list_get_instance(l, mbr_part_t, link); 236 encode_part(p, &(mbr->raw_data.pte[i]), 0); 237 l = l->next; 238 } 239 240 // Writing MBR 241 rc = block_write_direct(dev_handle, 0, 1, &(mbr->raw_data)); 242 if (rc != EOK) { 243 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 244 goto end; 245 } 198 246 199 247 if (ext == NULL) 200 248 goto no_extended; 201 249 250 202 251 uint32_t base = ext->start_addr; 203 252 uint32_t addr = base; 253 254 // Encoding and writing first logical partition 255 if (l != &(parts->list.head)) { 256 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 273 rc = block_write_direct(dev_handle, base, 1, p->ebr); 274 if (rc != EOK) { 275 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 276 goto end; 277 } 278 279 l = l->next; 280 } 281 282 283 284 // Encoding and writing logical partitions 285 while (l != &(parts->list.head)) { 286 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); 300 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); 305 if (rc != EOK) { 306 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); 307 goto end; 308 } 309 310 l = l->next; 311 } 312 313 no_extended: 314 315 /*if (ext == NULL) 316 goto no_extended; 317 318 uint32_t base = ext->start_addr; 319 uint32_t addr;// = base; 204 320 uint32_t prev_addr; 205 321 mbr_part_t * prev_part = NULL; … … 209 325 if (mbr_get_flag(p, ST_LOGIC)) { 210 326 // writing logical partition 211 212 if (p->start_addr < base || p->start_addr + p->length > base + ext->length) { 213 // out of bounds 214 return EINVAL; 215 } 216 217 327 logical = true; 328 218 329 if (p->ebr == NULL) { 219 330 p->ebr = alloc_br(); … … 225 336 } 226 337 227 228 229 230 338 if (prev_part != NULL) { 231 339 // addr is the address of EBR … … 243 351 addr = base; 244 352 // base-1 means start_lba+1 245 encode_part(p, &(p->ebr->pte[0]), base - 1); 353 // Fixed: mbr_add_partition now performs checks!nevim 354 encode_part(p, &(p->ebr->pte[0]), base); 246 355 } 247 356 248 357 //addr = p->start_addr; 249 358 prev_addr = addr; … … 260 369 ++i; 261 370 } 262 } 371 } //*/ 263 372 264 373 /* If there was an extended but no logical, we should overwrite … … 266 375 * might be some garbage from the past. 267 376 */ 268 377 /* 269 378 last_ebr = prev_part->ebr; 270 379 271 380 if (!logical) 272 381 { … … 276 385 goto end; 277 386 } 278 387 279 388 last_ebr->pte[0].ptype = PT_UNUSED; 280 389 } 281 282 390 391 283 392 encode_part(NULL, &(last_ebr->pte[1]), 0); 284 393 rc = block_write_direct(dev_handle, addr, 1, last_ebr); 285 394 286 395 if (!logical) 287 396 { 288 397 free(last_ebr); 289 398 } 290 399 */ 400 /* 291 401 if (rc != EOK) { 292 402 DEBUG_PRINT_2(LIBMBR_NAME ": Error (%d): %s.\n", rc, str_error(rc)); … … 297 407 298 408 no_extended: 299 409 */ 300 410 /*list_foreach(parts->list, it) { 301 411 p = list_get_instance(it, mbr_part_t, link); … … 313 423 } 314 424 }*/ 315 425 /* 316 426 it = parts->list.head.next; 317 427 for (i = 0; i < N_PRIMARY; i++) { … … 329 439 330 440 } 331 441 332 442 it = it->next; 333 443 } else { … … 335 445 } 336 446 } 337 447 338 448 339 449 skip: … … 343 453 goto end; 344 454 } 455 */ 345 456 346 457 /* … … 405 516 406 517 rc = EOK; 407 518 408 519 end: 409 520 block_fini(dev_handle); … … 437 548 438 549 list_initialize(&(parts->list)); 439 550 440 551 parts->n_primary = 0; 441 552 parts->n_logical = 0; … … 445 556 } 446 557 447 /** Add partition */ 558 /** Add partition 559 * Performs checks, sorts the list. 560 */ 448 561 int mbr_add_partition(mbr_partitions_t * parts, mbr_part_t * p) 449 562 { 450 list_append(&(p->link), &(parts->list));451 563 if (mbr_get_flag(p, ST_LOGIC)) { 564 // adding logical part 565 if (parts->l_extended == NULL) { 566 return ERR_NO_EXTENDED; 567 } 568 if (!check_encaps(p, list_get_instance(parts->l_extended, mbr_part_t, link))) { 569 return ERR_OUT_BOUNDS; 570 } 571 572 mbr_part_t * last = list_get_instance(list_last(&(parts->list)), mbr_part_t, link); 573 mbr_part_foreach(parts, iter) { 574 if (mbr_get_flag(iter, ST_LOGIC)) { 575 if (check_overlap(p, iter)) { 576 return ERR_OVERLAP; 577 } 578 if (check_preceeds(p, iter)) { 579 last = iter; 580 break; 581 } 582 } 583 } 584 585 //list_prepend(&(p->link), &(parts->list)); 586 list_insert_before(&(p->link), &(last->link)); 452 587 parts->n_logical += 1; 453 588 } else { 454 parts->n_primary += 1; 455 } 456 /* if we're adding new logical partition, we need 1 sector for the EBR 457 * for that partition (including the next one); we'd better make sure here 458 * before writing */ 459 if (mbr_get_flag(p, ST_LOGIC) && p->ebr == NULL) { 460 p->start_addr += 1; 461 p->length -= 1; 462 } 463 //FIXME: we can have multiple extended partitions! :-( 464 465 return EOK; 589 // adding primary 590 if (parts->n_primary == 4) { 591 return ERR_PRIMARY_FULL; 592 } 593 if (p->type == PT_EXTENDED && parts->l_extended != NULL) { 594 return ERR_EXTENDED_PRESENT; 595 } 596 597 if (list_empty(&(parts->list))) { 598 list_append(&(p->link), &(parts->list)); 599 } else { 600 mbr_part_foreach(parts, iter) { 601 if (mbr_get_flag(iter, ST_LOGIC)) { 602 list_insert_before(&(p->link), &(iter->link)); 603 parts->n_primary += 1; 604 break; 605 } else if (check_overlap(p, iter)) { 606 return ERR_OVERLAP; 607 } 608 } 609 } 610 } 611 612 return ERR_OK; 466 613 } 467 614 … … 469 616 int mbr_remove_partition(mbr_partitions_t * parts, size_t idx) 470 617 { 471 DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: % d\n", idx);618 DEBUG_PRINT_1(LIBMBR_NAME "Removing partition: %zu\n", idx); 472 619 link_t * l = list_nth(&(parts->list), idx); 473 620 if (l == parts->l_extended) { … … 482 629 parts->n_primary -= 1; 483 630 } 484 485 631 632 486 633 mbr_free_partition(p); 487 634 488 635 return EOK; 489 636 } … … 533 680 mbr_free_partition(p); 534 681 } 535 682 536 683 free(parts); 537 684 } … … 590 737 if (rc != EOK) 591 738 return rc; 592 739 593 740 ebr = alloc_br(); 594 741 if (ebr == NULL) { … … 606 753 goto free_ebr_end; 607 754 } 608 755 609 756 if (ebr->pte[0].ptype == PT_UNUSED) { 610 757 rc = EOK; 611 758 goto free_ebr_end; 612 759 } 613 760 614 761 p = mbr_alloc_partition(); 615 762 if (p == NULL) { … … 617 764 goto free_ebr_end; 618 765 } 619 766 620 767 621 768 decode_part(&(ebr->pte[0]), p, base); … … 625 772 626 773 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 627 774 628 775 while (ebr->pte[1].ptype != PT_UNUSED) { 629 776 ebr = alloc_br(); … … 656 803 addr = uint32_t_le2host(ebr->pte[1].first_lba) + base; 657 804 } 658 805 659 806 rc = EOK; 660 807 661 808 free_ebr_end: 662 809 free(ebr); 663 810 664 811 end: 665 812 block_fini(mbr->device); … … 690 837 } 691 838 839 static int check_overlap(mbr_part_t * p1, mbr_part_t * p2) 840 { 841 if (p1->start_addr < p2->start_addr && p1->start_addr + p1->length <= p2->start_addr) { 842 return 0; 843 } else if (p1->start_addr > p2->start_addr && p2->start_addr + p2->length <= p1->start_addr) { 844 return 0; 845 } 846 847 return 1; 848 } 849 850 static int check_encaps(mbr_part_t * inner, mbr_part_t * outer) 851 { 852 if (inner->start_addr <= outer->start_addr || outer->start_addr + outer->length <= inner->start_addr) { 853 return 0; 854 } else if (outer->start_addr + outer->length < inner->start_addr + inner->length) { 855 return 0; 856 } 857 858 return 1; 859 } 860 861 static int check_preceeds(mbr_part_t * preceeder, mbr_part_t * precedee) 862 { 863 return preceeder->start_addr < precedee->start_addr; 864 } 865 866 867 -
uspace/lib/mbr/libmbr.h
re91d17a rd617050 52 52 printf("%s:%d: " str, __FILE__, __LINE__, arg1, arg2, arg3) 53 53 #else 54 #define DEBUG_PRINT_0(str) 54 #define DEBUG_PRINT_0(str) 55 55 #define DEBUG_PRINT_1(str, arg1) 56 56 #define DEBUG_PRINT_2(str, arg1, arg2) … … 87 87 PT_GPT = 0xEE, 88 88 }; 89 90 typedef enum { 91 /** No error */ 92 ERR_OK = 0, 93 /** All primary partitions already present */ 94 ERR_PRIMARY_FULL, 95 /** Extended partition already present */ 96 ERR_EXTENDED_PRESENT, 97 /** No extended partition present */ 98 ERR_NO_EXTENDED, 99 /** Partition overlapping */ 100 ERR_OVERLAP, 101 /** Logical partition out of bounds */ 102 ERR_OUT_BOUNDS, 103 } MBR_ERR_VAL; 104 89 105 90 106 /** Structure of a partition table entry */ … … 146 162 /** Number of primary partitions */ 147 163 unsigned char n_primary; 148 /** Link to the extended partition in the list*/164 /** Index to the extended partition in the array */ 149 165 link_t * l_extended; 150 166 /** Number of logical partitions */ 151 167 unsigned int n_logical; 152 /** Partition linked list */168 /** Logical partition linked list */ 153 169 list_t list; 154 170 } mbr_partitions_t;
Note:
See TracChangeset
for help on using the changeset viewer.