1 /* $OpenBSD: partition_map.c,v 1.99 2019/07/31 00:14:10 krw Exp $ */ 2 3 /* 4 * partition_map.c - partition map routines 5 * 6 * Written by Eryk Vershen 7 */ 8 9 /* 10 * Copyright 1996,1997,1998 by Apple Computer, Inc. 11 * All Rights Reserved 12 * 13 * Permission to use, copy, modify, and distribute this software and 14 * its documentation for any purpose and without fee is hereby granted, 15 * provided that the above copyright notice appears in all copies and 16 * that both the copyright notice and this permission notice appear in 17 * supporting documentation. 18 * 19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE. 22 * 23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 28 */ 29 30 #include <sys/queue.h> 31 #include <sys/stdint.h> 32 33 #include <err.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 38 #include "partition_map.h" 39 #include "io.h" 40 #include "file_media.h" 41 42 #define APPLE_HFS_FLAGS_VALUE 0x4000037f 43 44 const char *kFreeType = "Apple_Free"; 45 const char *kMapType = "Apple_partition_map"; 46 const char *kUnixType = "OpenBSD"; 47 const char *kHFSType = "Apple_HFS"; 48 49 void combine_entry(struct entry *); 50 struct entry *create_entry(struct partition_map *, long, const char *, 51 const char *, uint32_t, uint32_t); 52 void delete_entry(struct entry *); 53 void insert_in_base_order(struct entry *); 54 void insert_in_disk_order(struct entry *); 55 int read_partition_map(struct partition_map *); 56 void remove_driver(struct entry *); 57 void renumber_disk_addresses(struct partition_map *); 58 59 struct partition_map * 60 open_partition_map(int fd, char *name, uint64_t mediasz, uint32_t sectorsz) 61 { 62 struct partition_map *map; 63 int ok; 64 65 map = malloc(sizeof(struct partition_map)); 66 if (map == NULL) 67 errx(1, "No memory to open partition map"); 68 69 map->fd = fd; 70 map->name = name; 71 72 map->changed = 0; 73 LIST_INIT(&map->disk_order); 74 LIST_INIT(&map->base_order); 75 map->blocks_in_map = 0; 76 map->maximum_in_map = -1; 77 78 if (mediasz > UINT32_MAX) 79 map->media_size = UINT32_MAX; 80 else 81 map->media_size = mediasz; 82 83 if (read_block0(map->fd, map) == 0) { 84 warnx("Can't read block 0 from '%s'", name); 85 free_partition_map(map); 86 return NULL; 87 } 88 if (map->sbSig == BLOCK0_SIGNATURE && 89 map->sbBlkSize == sectorsz && 90 map->sbBlkCount <= mediasz) { 91 if (read_partition_map(map) == 0) 92 return map; 93 } else { 94 if (map->sbSig != BLOCK0_SIGNATURE) 95 warnx("Block 0 signature: Expected 0x%04x, " 96 "got 0x%04x", BLOCK0_SIGNATURE, 97 map->sbSig); 98 else if (map->sbBlkSize != sectorsz) 99 warnx("Block 0 sbBlkSize (%u) != sector size (%u)", 100 map->sbBlkSize, sectorsz); 101 else if (map->sbBlkCount > mediasz) 102 warnx("Block 0 sbBlkCount (%u) > media size (%llu)", 103 map->sbBlkCount, 104 (unsigned long long)mediasz); 105 } 106 107 if (!lflag) { 108 my_ungetch('\n'); 109 printf("No valid partition map found on '%s'.\n", name); 110 ok = get_okay("Create default map? [n/y]: ", 0); 111 flush_to_newline(0); 112 if (ok == 1) { 113 free_partition_map(map); 114 map = create_partition_map(fd, name, mediasz, sectorsz); 115 if (map) 116 return map; 117 } 118 } 119 120 free_partition_map(map); 121 return NULL; 122 } 123 124 125 void 126 free_partition_map(struct partition_map *map) 127 { 128 struct entry *entry; 129 130 if (map == NULL) 131 return; 132 133 while (!LIST_EMPTY(&map->disk_order)) { 134 entry = LIST_FIRST(&map->disk_order); 135 LIST_REMOVE(entry, disk_entry); 136 free(entry); 137 } 138 139 free(map); 140 } 141 142 int 143 read_partition_map(struct partition_map *map) 144 { 145 struct entry *cur, *nextcur; 146 struct entry *entry; 147 int ix; 148 uint32_t limit, base, next, nextbase; 149 150 limit = 1; /* There has to be at least one, which has the real limit. */ 151 for (ix = 1; ix <= limit; ix++) { 152 entry = malloc(sizeof(struct entry)); 153 if (entry == NULL) 154 errx(1, "No memory for partition entry"); 155 if (read_dpme(map->fd, ix, entry) == 0) { 156 warnx("Can't read block %u from '%s'", ix, map->name); 157 free(entry); 158 return 1; 159 } 160 if (entry->dpme_signature != DPME_SIGNATURE) { 161 warnx("Invalid signature on block %d. Expected %x, " 162 "got %x", ix, DPME_SIGNATURE, 163 entry->dpme_signature); 164 free(entry); 165 return 1; 166 } 167 if (ix == 1) { 168 if (entry->dpme_map_entries > entry->dpme_pblocks) { 169 warnx("Map entry count (%u) > # of physical " 170 "blocks (%u)", entry->dpme_map_entries, 171 entry->dpme_pblocks); 172 free(entry); 173 return 1; 174 } 175 if (entry->dpme_map_entries == 0) { 176 warnx("Map entry count == 0. Must be > 0"); 177 free(entry); 178 return 1; 179 } 180 map->maximum_in_map = entry->dpme_pblocks; 181 limit = entry->dpme_map_entries; 182 } 183 if (limit != entry->dpme_map_entries) { 184 warnx("Invalid entry count on block %d. " 185 "Expected %d, got %d", ix, limit, 186 entry->dpme_map_entries); 187 free(entry); 188 return 1; 189 } 190 if (entry->dpme_lblock_start >= entry->dpme_pblocks) { 191 warnx("\tlogical start (%u) >= block count" 192 "count (%u).", entry->dpme_lblock_start, 193 entry->dpme_pblocks); 194 free(entry); 195 return 1; 196 } 197 if (entry->dpme_lblocks > entry->dpme_pblocks - 198 entry->dpme_lblock_start) { 199 warnx("\tlogical blocks (%u) > available blocks (%u).", 200 entry->dpme_lblocks, 201 entry->dpme_pblocks - entry->dpme_lblock_start); 202 free(entry); 203 return 1; 204 } 205 entry->the_map = map; 206 entry->disk_address = ix; 207 insert_in_disk_order(entry); 208 insert_in_base_order(entry); 209 map->blocks_in_map++; 210 } 211 212 /* Traverse base_order looking for 213 * 214 * 1) Overlapping partitions 215 * 2) Unmapped space 216 */ 217 LIST_FOREACH(cur, &map->base_order, base_entry) { 218 base = cur->dpme_pblock_start; 219 next = base + cur->dpme_pblocks; 220 if (base >= map->media_size || 221 next < base || 222 next > map->media_size) { 223 warnx("Partition extends past end of disk: %u -> %u", 224 base, next); 225 } 226 nextcur = LIST_NEXT(cur, base_entry); 227 if (nextcur) 228 nextbase = nextcur->dpme_pblock_start; 229 else 230 nextbase = map->media_size; 231 if (next != nextbase) 232 warnx("Unmapped pblocks: %u -> %u", next, nextbase); 233 if (next > nextbase) 234 warnx("Partition %ld overlaps next partition", 235 cur->disk_address); 236 } 237 238 return 0; 239 } 240 241 242 void 243 write_partition_map(struct partition_map *map) 244 { 245 struct entry *entry; 246 int result; 247 248 result = write_block0(map->fd, map); 249 if (result == 0) 250 warn("Unable to write block zero"); 251 252 LIST_FOREACH(entry, &map->disk_order, disk_entry) { 253 result = write_dpme(map->fd, entry->disk_address, entry); 254 if (result == 0) 255 warn("Unable to write block %ld", entry->disk_address); 256 } 257 } 258 259 260 struct partition_map * 261 create_partition_map(int fd, char *name, u_int64_t mediasz, uint32_t sectorsz) 262 { 263 struct partition_map *map; 264 struct entry *entry; 265 266 map = malloc(sizeof(struct partition_map)); 267 if (map == NULL) 268 errx(1, "No memory to create partition map"); 269 270 map->name = name; 271 map->fd = fd; 272 map->changed = 1; 273 LIST_INIT(&map->disk_order); 274 LIST_INIT(&map->base_order); 275 276 map->blocks_in_map = 0; 277 map->maximum_in_map = -1; 278 map->media_size = mediasz; 279 280 map->sbSig = BLOCK0_SIGNATURE; 281 map->sbBlkSize = sectorsz; 282 map->sbBlkCount = map->media_size; 283 284 entry = create_entry(map, 1, "", kFreeType, 1, mediasz - 1); 285 if (entry == NULL) 286 errx(1, "No memory for new dpme"); 287 288 add_partition_to_map("Apple", kMapType, 1, 289 (map->media_size <= 128 ? 2 : 63), map); 290 291 return map; 292 } 293 294 295 int 296 add_partition_to_map(const char *name, const char *dptype, uint32_t base, 297 uint32_t length, struct partition_map *map) 298 { 299 struct entry *cur; 300 int limit, new_entries; 301 uint32_t old_base, old_length, old_address; 302 uint32_t new_base, new_length; 303 304 if (map->maximum_in_map < 0) 305 limit = map->media_size; 306 else 307 limit = map->maximum_in_map; 308 309 /* find a block of free space that starts includes base and length */ 310 LIST_FOREACH(cur, &map->base_order, base_entry) { 311 if (strncasecmp(cur->dpme_type, kFreeType, DPISTRLEN)) 312 continue; 313 if (cur->dpme_pblock_start <= base && 314 (base + length) <= 315 (cur->dpme_pblock_start + cur->dpme_pblocks)) 316 break; 317 } 318 if (cur == NULL) { 319 printf("requested base and length is not " 320 "within an existing free partition\n"); 321 return 0; 322 } 323 old_base = cur->dpme_pblock_start; 324 old_length = cur->dpme_pblocks; 325 old_address = cur->disk_address; 326 327 /* Check that there is enough room in the map for the new entries! */ 328 if (base == old_base && length == old_length) 329 new_entries = 0; 330 else if (base == old_base) 331 new_entries = 1; 332 else if (base - old_base < old_length - length) 333 new_entries = 2; 334 else 335 new_entries = 1; 336 if (map->blocks_in_map + new_entries > limit) { 337 printf("the map is not big enough\n"); 338 return 0; 339 } 340 341 /* 342 * Delete old free entry from map and add back 1 to 3 new entries. 343 * 344 * 1) Empty space from base+len to old end. 345 * 2) New entry from specified base for length. 346 * 3) Empty space from old base to new base. 347 * 348 * All with the same disk address, so they must be added in that 349 * order! 350 */ 351 delete_entry(cur); 352 353 new_base = base + length; 354 new_length = (old_base + old_length) - new_base; 355 if (new_length > 0) { 356 /* New free space entry *after* new partition. */ 357 cur = create_entry(map, old_address, "", kFreeType, new_base, 358 new_length); 359 if (cur == NULL) 360 errx(1, "No memory for new dpme"); 361 } 362 363 cur = create_entry(map, old_address, name, dptype, base, length); 364 if (cur == NULL) 365 errx(1, "No memory for new entry"); 366 367 new_length = base - old_base; 368 if (new_length > 0) { 369 /* New free space entry *before* new partition. */ 370 cur = create_entry(map, old_address, "", kFreeType, old_base, 371 new_length); 372 if (cur == NULL) 373 errx(1, "No memory for new entry"); 374 } 375 376 renumber_disk_addresses(map); 377 map->changed = 1; 378 return 1; 379 } 380 381 382 struct entry* 383 create_entry(struct partition_map *map, long ix, const char *name, 384 const char *dptype, uint32_t base, uint32_t length) 385 { 386 struct entry *entry; 387 388 entry = calloc(1, sizeof(struct entry)); 389 if (entry == NULL) 390 errx(1, "No memory for new entry"); 391 392 entry->dpme_signature = DPME_SIGNATURE; 393 entry->dpme_map_entries = 1; 394 entry->dpme_pblock_start = base; 395 entry->dpme_pblocks = length; 396 strlcpy(entry->dpme_name, name, sizeof(entry->dpme_name)); 397 strlcpy(entry->dpme_type, dptype, sizeof(entry->dpme_type)); 398 if (strncasecmp(dptype, kFreeType, DPISTRLEN)) { 399 /* Only non-kFreeType entries get lblock info != 0. */ 400 entry->dpme_lblocks = entry->dpme_pblocks; 401 } 402 dpme_init_flags(entry); 403 404 entry->disk_address = ix; 405 entry->the_map = map; 406 407 insert_in_disk_order(entry); 408 insert_in_base_order(entry); 409 410 map->blocks_in_map++; 411 if (map->maximum_in_map < 0) { 412 if (strncasecmp(entry->dpme_type, kMapType, DPISTRLEN) == 0) 413 map->maximum_in_map = entry->dpme_pblocks; 414 } 415 416 return entry; 417 } 418 419 void 420 dpme_init_flags(struct entry *entry) 421 { 422 if (strncasecmp(entry->dpme_type, kFreeType, DPISTRLEN) == 0) 423 entry->dpme_flags = 0; 424 else if (strncasecmp(entry->dpme_type, kMapType, DPISTRLEN) == 0) 425 entry->dpme_flags = DPME_VALID | DPME_ALLOCATED; 426 else if (strncasecmp(entry->dpme_type, kHFSType, DPISTRLEN) == 0) 427 entry->dpme_flags = APPLE_HFS_FLAGS_VALUE; 428 else 429 entry->dpme_flags = DPME_VALID | DPME_ALLOCATED | 430 DPME_READABLE | DPME_WRITABLE; 431 } 432 433 void 434 renumber_disk_addresses(struct partition_map *map) 435 { 436 struct entry *cur; 437 long ix; 438 439 /* reset disk addresses */ 440 ix = 1; 441 LIST_FOREACH(cur, &map->disk_order, disk_entry) { 442 cur->disk_address = ix++; 443 cur->dpme_map_entries = map->blocks_in_map; 444 } 445 } 446 447 void 448 delete_partition_from_map(struct entry *entry) 449 { 450 struct partition_map *map; 451 uint32_t base, length, address; 452 453 if (strncasecmp(entry->dpme_type, kMapType, DPISTRLEN) == 0) { 454 printf("Can't delete entry for the map itself\n"); 455 return; 456 } 457 if (strncasecmp(entry->dpme_type, kFreeType, DPISTRLEN) == 0) { 458 printf("Can't delete entry for free space\n"); 459 return; 460 } 461 if (contains_driver(entry)) { 462 printf("This program can't install drivers\n"); 463 if (get_okay("are you sure you want to delete this driver? " 464 "[n/y]: ", 0) != 1) { 465 return; 466 } 467 remove_driver(entry); /* update block0 if necessary */ 468 } 469 470 map = entry->the_map; 471 base = entry->dpme_pblock_start; 472 length = entry->dpme_pblocks; 473 address = entry->disk_address; 474 475 delete_entry(entry); 476 entry = create_entry(map, address, "" , kFreeType, base, length); 477 combine_entry(entry); 478 renumber_disk_addresses(entry->the_map); 479 entry->the_map->changed = 1; 480 } 481 482 483 int 484 contains_driver(struct entry *entry) 485 { 486 struct partition_map *map; 487 struct ddmap *m; 488 int i; 489 uint32_t start; 490 491 map = entry->the_map; 492 m = map->sbDDMap; 493 for (i = 0; i < map->sbDrvrCount; i++) { 494 start = m[i].ddBlock; 495 if (entry->dpme_pblock_start <= start && 496 (start + m[i].ddSize) <= (entry->dpme_pblock_start + 497 entry->dpme_pblocks)) 498 return 1; 499 } 500 501 return 0; 502 } 503 504 505 void 506 combine_entry(struct entry *entry) 507 { 508 struct entry *p; 509 uint32_t end; 510 511 if (entry == NULL || 512 strncasecmp(entry->dpme_type, kFreeType, DPISTRLEN) != 0) 513 return; 514 515 p = LIST_NEXT(entry, base_entry); 516 if (p != NULL) { 517 if (strncasecmp(p->dpme_type, kFreeType, DPISTRLEN) != 518 0) { 519 /* next is not free */ 520 } else if (entry->dpme_pblock_start + 521 entry->dpme_pblocks != p->dpme_pblock_start) { 522 /* next is not contiguous (XXX this is bad) */ 523 printf("next entry is not contiguous\n"); 524 /* start is already minimum */ 525 /* new end is maximum of two ends */ 526 end = p->dpme_pblock_start + p->dpme_pblocks; 527 if (end > entry->dpme_pblock_start + 528 entry->dpme_pblocks) { 529 entry->dpme_pblocks = end - 530 entry->dpme_pblock_start; 531 } 532 delete_entry(p); 533 } else { 534 entry->dpme_pblocks += p->dpme_pblocks; 535 delete_entry(p); 536 } 537 } 538 539 LIST_FOREACH(p, &entry->the_map->base_order, base_entry) { 540 if (LIST_NEXT(p, base_entry) == entry) 541 break; 542 } 543 if (p != NULL) { 544 if (strncasecmp(p->dpme_type, kFreeType, DPISTRLEN) != 0) { 545 /* previous is not free */ 546 } else if (p->dpme_pblock_start + p->dpme_pblocks != 547 entry->dpme_pblock_start) { 548 /* previous is not contiguous (XXX this is bad) */ 549 printf("previous entry is not contiguous\n"); 550 /* new end is maximum of two ends */ 551 end = p->dpme_pblock_start + p->dpme_pblocks; 552 if (end < entry->dpme_pblock_start + 553 entry->dpme_pblocks) { 554 end = entry->dpme_pblock_start + 555 entry->dpme_pblocks; 556 } 557 entry->dpme_pblocks = end - p->dpme_pblock_start; 558 entry->dpme_pblock_start = p->dpme_pblock_start; 559 delete_entry(p); 560 } else { 561 entry->dpme_pblock_start = p->dpme_pblock_start; 562 entry->dpme_pblocks += p->dpme_pblocks; 563 delete_entry(p); 564 } 565 } 566 } 567 568 569 void 570 delete_entry(struct entry *entry) 571 { 572 struct partition_map *map; 573 574 map = entry->the_map; 575 map->blocks_in_map--; 576 577 LIST_REMOVE(entry, disk_entry); 578 LIST_REMOVE(entry, base_entry); 579 580 free(entry); 581 } 582 583 584 struct entry * 585 find_entry_by_disk_address(long ix, struct partition_map *map) 586 { 587 struct entry *cur; 588 589 LIST_FOREACH(cur, &map->disk_order, disk_entry) { 590 if (cur->disk_address == ix) 591 break; 592 } 593 return cur; 594 } 595 596 597 struct entry * 598 find_entry_by_type(const char *type_name, struct partition_map *map) 599 { 600 struct entry *cur; 601 602 LIST_FOREACH(cur, &map->base_order, base_entry) { 603 if (strncasecmp(cur->dpme_type, type_name, DPISTRLEN) == 0) 604 break; 605 } 606 return cur; 607 } 608 609 struct entry * 610 find_entry_by_base(uint32_t base, struct partition_map *map) 611 { 612 struct entry *cur; 613 614 LIST_FOREACH(cur, &map->base_order, base_entry) { 615 if (cur->dpme_pblock_start == base) 616 break; 617 } 618 return cur; 619 } 620 621 622 void 623 move_entry_in_map(long index1, long index2, struct partition_map *map) 624 { 625 struct entry *p1, *p2; 626 627 if (index1 == index2) 628 return; 629 630 if (index1 == 1 || index2 == 1) { 631 printf("Partition #1 cannot be moved\n"); 632 return; 633 } 634 p1 = find_entry_by_disk_address(index1, map); 635 if (p1 == NULL) { 636 printf("Partition #%ld not found\n", index1); 637 return; 638 } 639 p2 = find_entry_by_disk_address(index2, map); 640 if (p2 == NULL) { 641 printf("Partition #%ld not found\n", index2); 642 return; 643 } 644 645 LIST_REMOVE(p1, disk_entry); 646 LIST_REMOVE(p2, disk_entry); 647 648 p1->disk_address = index2; 649 p2->disk_address = index1; 650 651 insert_in_disk_order(p1); 652 insert_in_disk_order(p2); 653 654 renumber_disk_addresses(map); 655 map->changed = 1; 656 } 657 658 659 void 660 insert_in_disk_order(struct entry *entry) 661 { 662 struct partition_map *map; 663 struct entry *cur; 664 665 /* find position in disk list & insert */ 666 map = entry->the_map; 667 if (LIST_EMPTY(&map->disk_order)) { 668 LIST_INSERT_HEAD(&map->disk_order, entry, disk_entry); 669 return; 670 } 671 672 LIST_FOREACH(cur, &map->disk_order, disk_entry) { 673 if (cur->disk_address >= entry->disk_address) { 674 LIST_INSERT_BEFORE(cur, entry, disk_entry); 675 return; 676 } 677 if (LIST_NEXT(cur, disk_entry) == NULL) { 678 LIST_INSERT_AFTER(cur, entry, disk_entry); 679 return; 680 } 681 } 682 } 683 684 685 void 686 insert_in_base_order(struct entry *entry) 687 { 688 struct partition_map *map; 689 struct entry *cur; 690 uint32_t start; 691 692 /* find position in base list & insert */ 693 map = entry->the_map; 694 if (LIST_EMPTY(&map->base_order)) { 695 LIST_INSERT_HEAD(&map->base_order, entry, base_entry); 696 return; 697 } 698 699 start = entry->dpme_pblock_start; 700 LIST_FOREACH(cur, &map->base_order, base_entry) { 701 if (start <= cur->dpme_pblock_start) { 702 LIST_INSERT_BEFORE(cur, entry, base_entry); 703 return; 704 } 705 if (LIST_NEXT(cur, base_entry) == NULL) { 706 LIST_INSERT_AFTER(cur, entry, base_entry); 707 return; 708 } 709 } 710 } 711 712 713 void 714 resize_map(long new_size, struct partition_map *map) 715 { 716 struct entry *entry; 717 struct entry *next; 718 int incr; 719 720 entry = find_entry_by_type(kMapType, map); 721 722 if (entry == NULL) { 723 printf("Couldn't find entry for map!\n"); 724 return; 725 } 726 if (new_size == entry->dpme_pblocks) 727 return; 728 729 next = LIST_NEXT(entry, base_entry); 730 731 if (new_size < entry->dpme_pblocks) { 732 /* make it smaller */ 733 if (next == NULL || 734 strncasecmp(next->dpme_type, kFreeType, DPISTRLEN) != 0) 735 incr = 1; 736 else 737 incr = 0; 738 if (new_size < map->blocks_in_map + incr) { 739 printf("New size would be too small\n"); 740 return; 741 } 742 goto doit; 743 } 744 /* make it larger */ 745 if (next == NULL || 746 strncasecmp(next->dpme_type, kFreeType, DPISTRLEN) != 0) { 747 printf("No free space to expand into\n"); 748 return; 749 } 750 if (entry->dpme_pblock_start + entry->dpme_pblocks 751 != next->dpme_pblock_start) { 752 printf("No contiguous free space to expand into\n"); 753 return; 754 } 755 if (new_size > entry->dpme_pblocks + next->dpme_pblocks) { 756 printf("No enough free space\n"); 757 return; 758 } 759 doit: 760 entry->dpme_type[0] = 0; 761 delete_partition_from_map(entry); 762 add_partition_to_map("Apple", kMapType, 1, new_size, map); 763 map->maximum_in_map = new_size; 764 } 765 766 767 void 768 remove_driver(struct entry *entry) 769 { 770 struct partition_map *map; 771 struct ddmap *m; 772 int i, j; 773 uint32_t start; 774 775 /* 776 * compute the factor to convert the block numbers in block0 777 * into partition map block numbers. 778 */ 779 map = entry->the_map; 780 m = map->sbDDMap; 781 for (i = 0; i < map->sbDrvrCount; i++) { 782 start = m[i].ddBlock; 783 /* 784 * zap the driver if it is wholly contained in the 785 * partition 786 */ 787 if (entry->dpme_pblock_start <= start && (start + 788 m[i].ddSize) <= (entry->dpme_pblock_start + 789 entry->dpme_pblocks)) { 790 /* 791 * Delete this driver by copying down later ones and 792 * zapping the last one. 793 */ 794 for (j = i + 1; j < map->sbDrvrCount; j++, i++) { 795 m[i].ddBlock = m[i].ddBlock; 796 m[i].ddSize = m[j].ddSize; 797 m[i].ddType = m[j].ddType; 798 } 799 m[i].ddBlock = 0; 800 m[i].ddSize = 0; 801 m[i].ddType = 0; 802 map->sbDrvrCount -= 1; 803 return; /* XXX if we continue we will delete 804 * other drivers? */ 805 } 806 } 807 } 808