1 // 2 // dump.c - dumping partition maps 3 // 4 // Written by Eryk Vershen 5 // 6 7 /* 8 * Copyright 1996,1997,1998 by Apple Computer, Inc. 9 * All Rights Reserved 10 * 11 * Permission to use, copy, modify, and distribute this software and 12 * its documentation for any purpose and without fee is hereby granted, 13 * provided that the above copyright notice appears in all copies and 14 * that both the copyright notice and this permission notice appear in 15 * supporting documentation. 16 * 17 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 19 * FOR A PARTICULAR PURPOSE. 20 * 21 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR 22 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 23 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, 24 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 25 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 26 */ 27 28 // for *printf() 29 #include <stdio.h> 30 31 // for malloc() & free() 32 #ifndef __linux__ 33 #include <stdlib.h> 34 //#include <unistd.h> 35 #else 36 #include <malloc.h> 37 #endif 38 39 // for strcmp() 40 #include <string.h> 41 // for O_RDONLY 42 #include <fcntl.h> 43 // for errno 44 #include <errno.h> 45 #include <inttypes.h> 46 47 #include "dump.h" 48 #include "pathname.h" 49 #include "io.h" 50 #include "errors.h" 51 52 53 // 54 // Defines 55 // 56 #if DPISTRLEN != 32 57 #error Change in strlen in partition entries! Fix constants 58 #endif 59 60 #define get_align_long(x) (*(x)) 61 62 63 // 64 // Types 65 // 66 typedef struct names { 67 const char *abbr; 68 const char *full; 69 } NAMES; 70 71 #ifdef __unix__ 72 typedef uint32_t OSType; 73 #endif 74 75 typedef struct PatchDescriptor { 76 OSType patchSig; 77 uint16_t majorVers; 78 uint16_t minorVers; 79 uint32_t flags; 80 uint32_t patchOffset; 81 uint32_t patchSize; 82 uint32_t patchCRC; 83 uint32_t patchDescriptorLen; 84 uint8_t patchName[33]; 85 uint8_t patchVendor[1]; 86 } PatchDescriptor; 87 typedef PatchDescriptor * PatchDescriptorPtr; 88 89 typedef struct PatchList { 90 uint16_t numPatchBlocks; // number of disk blocks to hold the patch list 91 uint16_t numPatches; // number of patches in list 92 PatchDescriptor thePatch[1]; 93 } PatchList; 94 typedef PatchList *PatchListPtr; 95 96 97 // 98 // Global Constants 99 // 100 NAMES plist[] = { 101 {"Drvr", "Apple_Driver"}, 102 {"Drv4", "Apple_Driver43"}, 103 {"Free", "Apple_Free"}, 104 {"Patc", "Apple_Patches"}, 105 {" HFS", "Apple_HFS"}, 106 {" MFS", "Apple_MFS"}, 107 {"PDOS", "Apple_PRODOS"}, 108 {"junk", "Apple_Scratch"}, 109 {"unix", "Apple_UNIX_SVR2"}, 110 {" map", "Apple_partition_map"}, 111 {0, 0}, 112 }; 113 114 const char * kStringEmpty = ""; 115 const char * kStringNot = " not"; 116 117 118 // 119 // Global Variables 120 // 121 int aflag = AFLAG_DEFAULT; /* abbreviate partition types */ 122 int pflag = PFLAG_DEFAULT; /* show physical limits of partition */ 123 int fflag = FFLAG_DEFAULT; /* show HFS volume names */ 124 125 126 // 127 // Forward declarations 128 // 129 void adjust_value_and_compute_prefix(double *value, int *prefix); 130 void dump_block_zero(partition_map_header *map); 131 void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits); 132 int get_max_base_or_length(partition_map_header *map); 133 int get_max_name_string_length(partition_map_header *map); 134 int get_max_type_string_length(partition_map_header *map); 135 136 137 // 138 // Routines 139 // 140 int 141 dump(char *name) 142 { 143 partition_map_header *map; 144 int junk; 145 146 map = open_partition_map(name, &junk, 0); 147 if (map == NULL) { 148 //error(-1, "No partition map in '%s'", name); 149 return 0; 150 } 151 152 dump_partition_map(map, 1); 153 154 close_partition_map(map); 155 156 return 1; 157 } 158 159 160 void 161 dump_block_zero(partition_map_header *map) 162 { 163 Block0 *p; 164 DDMap *m; 165 int i; 166 double value; 167 int prefix; 168 int32_t t; 169 170 p = map->misc; 171 if (p->sbSig != BLOCK0_SIGNATURE) { 172 return; 173 } 174 175 value = ((double)p->sbBlkCount) * p->sbBlkSize; 176 adjust_value_and_compute_prefix(&value, &prefix); 177 printf("\nDevice block size=%u, Number of Blocks=%"PRIu32" (%1.1f%c)\n", 178 p->sbBlkSize, p->sbBlkCount, value, prefix); 179 180 printf("DeviceType=0x%x, DeviceId=0x%x\n", 181 p->sbDevType, p->sbDevId); 182 if (p->sbDrvrCount > 0) { 183 printf("Drivers-\n"); 184 m = (DDMap *) p->sbMap; 185 for (i = 0; i < p->sbDrvrCount; i++) { 186 printf("%u: %3u @ %"PRIu32", ", i+1, 187 m[i].ddSize, get_align_long(&m[i].ddBlock)); 188 if (map->logical_block != p->sbBlkSize) { 189 t = (m[i].ddSize * p->sbBlkSize) / map->logical_block; 190 printf("(%"PRIu32"@", t); 191 t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize) 192 / map->logical_block; 193 printf("%"PRIu32") ", t); 194 } 195 printf("type=0x%x\n", m[i].ddType); 196 } 197 } 198 printf("\n"); 199 } 200 201 202 void 203 dump_partition_map(partition_map_header *map, int disk_order) 204 { 205 partition_map * entry; 206 int max_type_length; 207 int max_name_length; 208 int digits; 209 char *alternate; 210 211 if (map == NULL) { 212 bad_input("No partition map exists"); 213 return; 214 } 215 alternate = get_linux_name(map->name); 216 if (alternate) { 217 printf("\nPartition map (with %d byte blocks) on '%s' (%s)\n", 218 map->logical_block, map->name, alternate); 219 free(alternate); 220 } else { 221 printf("\nPartition map (with %d byte blocks) on '%s'\n", 222 map->logical_block, map->name); 223 } 224 225 digits = number_of_digits(get_max_base_or_length(map)); 226 if (digits < 6) { 227 digits = 6; 228 } 229 if (aflag) { 230 max_type_length = 4; 231 } else { 232 max_type_length = get_max_type_string_length(map); 233 if (max_type_length < 4) { 234 max_type_length = 4; 235 } 236 } 237 max_name_length = get_max_name_string_length(map); 238 if (max_name_length < 6) { 239 max_name_length = 6; 240 } 241 printf(" #: %*s %-*s %*s %-*s ( size )\n", 242 max_type_length, "type", 243 max_name_length, "name", 244 digits, "length", digits, "base"); 245 246 if (disk_order) { 247 for (entry = map->disk_order; entry != NULL; 248 entry = entry->next_on_disk) { 249 250 dump_partition_entry(entry, max_type_length, max_name_length, digits); 251 } 252 } else { 253 for (entry = map->base_order; entry != NULL; 254 entry = entry->next_by_base) { 255 256 dump_partition_entry(entry, max_type_length, max_name_length, digits); 257 } 258 } 259 dump_block_zero(map); 260 } 261 262 263 void 264 dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits) 265 { 266 partition_map_header *map; 267 int j; 268 DPME *p; 269 const char *s; 270 uint32_t size; 271 double bytes; 272 int driver; 273 // int kind; 274 char *buf; 275 #if 1 276 BZB *bp; 277 #endif 278 279 map = entry->the_map; 280 p = entry->data; 281 driver = entry->contains_driver? '*': ' '; 282 if (aflag) { 283 s = "????"; 284 for (j = 0; plist[j].abbr != 0; j++) { 285 if (strcmp(p->dpme_type, plist[j].full) == 0) { 286 s = plist[j].abbr; 287 break; 288 } 289 } 290 printf("%2"PRIu32": %.4s", entry->disk_address, s); 291 } else { 292 printf("%2"PRIu32": %*.32s", entry->disk_address, type_length, p->dpme_type); 293 } 294 295 buf = (char *) malloc(name_length+1); 296 if (entry->HFS_name == NULL || fflag == 0) { 297 strncpy(buf, p->dpme_name, name_length); 298 buf[name_length] = 0; 299 } else { 300 snprintf(buf, name_length + 1, "\"%s\"", entry->HFS_name); 301 } 302 printf("%c%-*.32s ", driver, name_length, buf); 303 free(buf); 304 /* 305 switch (entry->HFS_kind) { 306 case kHFS_std: kind = 'h'; break; 307 case kHFS_embed: kind = 'e'; break; 308 case kHFS_plus: kind = '+'; break; 309 default: 310 case kHFS_not: kind = ' '; break; 311 } 312 printf("%c ", kind); 313 */ 314 315 if (pflag) { 316 printf("%*"PRIu32" ", digits, p->dpme_pblocks); 317 size = p->dpme_pblocks; 318 } else if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) { 319 printf("%*"PRIu32"+", digits, p->dpme_lblocks); 320 size = p->dpme_lblocks; 321 } else if (p->dpme_lblock_start != 0) { 322 printf("%*"PRIu32" ", digits, p->dpme_lblocks); 323 size = p->dpme_lblocks; 324 } else { 325 printf("%*"PRIu32" ", digits, p->dpme_pblocks); 326 size = p->dpme_pblocks; 327 } 328 if (pflag || p->dpme_lblock_start == 0) { 329 printf("@ %-*"PRIu32"", digits, p->dpme_pblock_start); 330 } else { 331 printf("@~%-*"PRIu32"", digits, p->dpme_pblock_start + p->dpme_lblock_start); 332 } 333 334 bytes = ((double)size) * map->logical_block; 335 adjust_value_and_compute_prefix(&bytes, &j); 336 if (j != ' ' && j != 'K') { 337 printf(" (%#5.1f%c)", bytes, j); 338 } 339 340 #if 1 341 // Old A/UX fields that no one pays attention to anymore. 342 bp = (BZB *) (p->dpme_bzb); 343 j = -1; 344 if (bp->bzb_magic == BZBMAGIC) { 345 switch (bp->bzb_type) { 346 case FSTEFS: 347 s = "EFS"; 348 break; 349 case FSTSFS: 350 s = "SFS"; 351 j = 1; 352 break; 353 case FST: 354 default: 355 if (bzb_root_get(bp) != 0) { 356 if (bzb_usr_get(bp) != 0) { 357 s = "RUFS"; 358 } else { 359 s = "RFS"; 360 } 361 j = 0; 362 } else if (bzb_usr_get(bp) != 0) { 363 s = "UFS"; 364 j = 2; 365 } else { 366 s = "FS"; 367 } 368 break; 369 } 370 if (bzb_slice_get(bp) != 0) { 371 printf(" s%1"PRId32" %4s", bzb_slice_get(bp)-1, s); 372 } else if (j >= 0) { 373 printf(" S%1d %4s", j, s); 374 } else { 375 printf(" %4s", s); 376 } 377 if (bzb_crit_get(bp) != 0) { 378 printf(" K%1d", bp->bzb_cluster); 379 } else if (j < 0) { 380 printf(" "); 381 } else { 382 printf(" k%1d", bp->bzb_cluster); 383 } 384 if (bp->bzb_mount_point[0] != 0) { 385 printf(" %.64s", bp->bzb_mount_point); 386 } 387 } 388 #endif 389 printf("\n"); 390 } 391 392 393 void 394 list_all_disks(void) 395 { 396 MEDIA_ITERATOR iter; 397 MEDIA m; 398 DPME * data; 399 char *name; 400 long mark; 401 402 data = (DPME *) malloc(PBLOCK_SIZE); 403 if (data == NULL) { 404 error(errno, "can't allocate memory for try buffer"); 405 return; 406 } 407 408 for (iter = first_media_kind(&mark); iter != 0; iter = next_media_kind(&mark)) { 409 410 while ((name = step_media_iterator(iter)) != 0) { 411 412 if ((m = open_pathname_as_media(name, O_RDONLY)) == 0) { 413 #if defined(__linux__) || defined(__unix__) 414 error(errno, "can't open file '%s'", name); 415 #endif 416 } else { 417 close_media(m); 418 419 dump(name); 420 } 421 free(name); 422 } 423 424 delete_media_iterator(iter); 425 } 426 427 free(data); 428 } 429 430 431 void 432 show_data_structures(partition_map_header *map) 433 { 434 Block0 *zp; 435 DDMap *m; 436 int i; 437 int j; 438 partition_map * entry; 439 DPME *p; 440 BZB *bp; 441 const char *s; 442 443 if (map == NULL) { 444 printf("No partition map exists\n"); 445 return; 446 } 447 printf("Header:\n"); 448 printf("map %d blocks out of %d, media %"PRIu32" blocks (%d byte blocks)\n", 449 map->blocks_in_map, map->maximum_in_map, 450 map->media_size, map->logical_block); 451 printf("Map is%s writable", (map->writable)?kStringEmpty:kStringNot); 452 printf(", but%s changed", (map->changed)?kStringEmpty:kStringNot); 453 printf(" and has%s been written\n", (map->written)?kStringEmpty:kStringNot); 454 printf("\n"); 455 456 if (map->misc == NULL) { 457 printf("No block zero\n"); 458 } else { 459 zp = map->misc; 460 461 printf("Block0:\n"); 462 printf("signature 0x%x", zp->sbSig); 463 if (zp->sbSig == BLOCK0_SIGNATURE) { 464 printf("\n"); 465 } else { 466 printf(" should be 0x%x\n", BLOCK0_SIGNATURE); 467 } 468 printf("Block size=%u, Number of Blocks=%"PRIu32"\n", 469 zp->sbBlkSize, zp->sbBlkCount); 470 printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%"PRIx32"\n", 471 zp->sbDevType, zp->sbDevId, zp->sbData); 472 if (zp->sbDrvrCount == 0) { 473 printf("No drivers\n"); 474 } else { 475 printf("%u driver%s-\n", zp->sbDrvrCount, 476 (zp->sbDrvrCount>1)?"s":kStringEmpty); 477 m = (DDMap *) zp->sbMap; 478 for (i = 0; i < zp->sbDrvrCount; i++) { 479 printf("%u: @ %"PRIu32" for %u, type=0x%x\n", i+1, 480 get_align_long(&m[i].ddBlock), 481 m[i].ddSize, m[i].ddType); 482 } 483 } 484 } 485 printf("\n"); 486 487 /* 488 uint32_t dpme_boot_args[32] ; 489 uint32_t dpme_reserved_3[62] ; 490 */ 491 printf(" #: type length base " 492 "flags (logical)\n"); 493 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 494 p = entry->data; 495 printf("%2"PRIu32": %20.32s ", 496 entry->disk_address, p->dpme_type); 497 printf("%7"PRIu32" @ %-7"PRIu32" ", p->dpme_pblocks, p->dpme_pblock_start); 498 printf("%c%c%c%c%c%c%c%c%c%c%c%c ", 499 (dpme_valid_get(p))?'V':'.', 500 (dpme_allocated_get(p))?'A':'.', 501 (dpme_in_use_get(p))?'I':'.', 502 (dpme_bootable_get(p))?'B':'.', 503 (dpme_readable_get(p))?'R':'.', 504 (dpme_writable_get(p))?'W':'.', 505 (dpme_os_pic_code_get(p))?'P':'.', 506 (dpme_os_specific_2_get(p))?'2':'.', 507 (dpme_chainable_get(p))?'C':'.', 508 (dpme_diskdriver_get(p))?'D':'.', 509 (bitfield_get(p->dpme_flags, 30, 1))?'M':'.', 510 (bitfield_get(p->dpme_flags, 31, 1))?'X':'.'); 511 if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) { 512 printf("(%"PRIu32" @ %"PRIu32")", p->dpme_lblocks, p->dpme_lblock_start); 513 } 514 printf("\n"); 515 } 516 printf("\n"); 517 printf(" #: booter bytes load_address " 518 "goto_address checksum processor\n"); 519 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 520 p = entry->data; 521 printf("%2"PRIu32": ", entry->disk_address); 522 printf("%7"PRIu32" ", p->dpme_boot_block); 523 printf("%7"PRIu32" ", p->dpme_boot_bytes); 524 printf("%8"PRIx32" ", (uint32_t)p->dpme_load_addr); 525 printf("%8"PRIx32" ", (uint32_t)p->dpme_load_addr_2); 526 printf("%8"PRIx32" ", (uint32_t)p->dpme_goto_addr); 527 printf("%8"PRIx32" ", (uint32_t)p->dpme_goto_addr_2); 528 printf("%8"PRIx32" ", p->dpme_checksum); 529 printf("%.32s", p->dpme_process_id); 530 printf("\n"); 531 } 532 printf("\n"); 533 /* 534 xx: cccc RU *dd s... 535 */ 536 printf(" #: type RU *slice mount_point (A/UX only fields)\n"); 537 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 538 p = entry->data; 539 printf("%2"PRIu32": ", entry->disk_address); 540 541 bp = (BZB *) (p->dpme_bzb); 542 j = -1; 543 if (bp->bzb_magic == BZBMAGIC) { 544 switch (bp->bzb_type) { 545 case FSTEFS: 546 s = "esch"; 547 break; 548 case FSTSFS: 549 s = "swap"; 550 j = 1; 551 break; 552 case FST: 553 default: 554 s = "fsys"; 555 if (bzb_root_get(bp) != 0) { 556 j = 0; 557 } else if (bzb_usr_get(bp) != 0) { 558 j = 2; 559 } 560 break; 561 } 562 printf("%4s ", s); 563 printf("%c%c ", 564 (bzb_root_get(bp))?'R':' ', 565 (bzb_usr_get(bp))?'U':' '); 566 if (bzb_slice_get(bp) != 0) { 567 printf(" %2"PRIu32"", bzb_slice_get(bp)-1); 568 } else if (j >= 0) { 569 printf(" *%2d", j); 570 } else { 571 printf(" "); 572 } 573 if (bp->bzb_mount_point[0] != 0) { 574 printf(" %.64s", bp->bzb_mount_point); 575 } 576 } 577 printf("\n"); 578 } 579 } 580 581 582 void 583 full_dump_partition_entry(partition_map_header *map, int ix) 584 { 585 partition_map * cur; 586 DPME *p; 587 int i; 588 uint32_t t; 589 590 cur = find_entry_by_disk_address(ix, map); 591 if (cur == NULL) { 592 printf("No such partition\n"); 593 return; 594 } 595 596 p = cur->data; 597 printf(" signature: 0x%x\n", p->dpme_signature); 598 printf(" reserved1: 0x%x\n", p->dpme_reserved_1); 599 printf(" number of map entries: %"PRId32"\n", p->dpme_map_entries); 600 printf(" physical start: %10"PRIu32" length: %10"PRIu32"\n", p->dpme_pblock_start, p->dpme_pblocks); 601 printf(" logical start: %10"PRIu32" length: %10"PRIu32"\n", p->dpme_lblock_start, p->dpme_lblocks); 602 603 printf(" flags: 0x%"PRIx32"\n", (uint32_t)p->dpme_flags); 604 printf(" "); 605 if (dpme_valid_get(p)) printf("valid "); 606 if (dpme_allocated_get(p)) printf("alloc "); 607 if (dpme_in_use_get(p)) printf("in-use "); 608 if (dpme_bootable_get(p)) printf("boot "); 609 if (dpme_readable_get(p)) printf("read "); 610 if (dpme_writable_get(p)) printf("write "); 611 if (dpme_os_pic_code_get(p)) printf("pic "); 612 t = p->dpme_flags >> 7; 613 for (i = 7; i <= 31; i++) { 614 if (t & 0x1) { 615 printf("%d ", i); 616 } 617 t = t >> 1; 618 } 619 printf("\n"); 620 621 printf(" name: '%.32s'\n", p->dpme_name); 622 printf(" type: '%.32s'\n", p->dpme_type); 623 624 printf(" boot start block: %10"PRIu32"\n", p->dpme_boot_block); 625 printf("boot length (in bytes): %10"PRIu32"\n", p->dpme_boot_bytes); 626 printf(" load address: 0x%08"PRIx32" 0x%08"PRIx32"\n", 627 (uint32_t)p->dpme_load_addr, (uint32_t)p->dpme_load_addr_2); 628 printf(" start address: 0x%08"PRIx32" 0x%08"PRIx32"\n", 629 (uint32_t)p->dpme_goto_addr, (uint32_t)p->dpme_goto_addr_2); 630 printf(" checksum: 0x%08"PRIx32"\n", p->dpme_checksum); 631 printf(" processor: '%.32s'\n", p->dpme_process_id); 632 printf("boot args field -"); 633 dump_block((uint8_t *)p->dpme_boot_args, 32*4); 634 printf("dpme_reserved_3 -"); 635 dump_block((uint8_t *)p->dpme_reserved_3, 62*4); 636 } 637 638 639 void 640 dump_block(uint8_t *addr, int len) 641 { 642 int i; 643 int j; 644 int limit1; 645 int limit; 646 #define LINE_LEN 16 647 #define UNIT_LEN 4 648 #define OTHER_LEN 8 649 650 for (i = 0; i < len; i = limit) { 651 limit1 = i + LINE_LEN; 652 if (limit1 > len) { 653 limit = len; 654 } else { 655 limit = limit1; 656 } 657 printf("\n%03x: ", i); 658 for (j = i; j < limit1; j++) { 659 if (j % UNIT_LEN == 0) { 660 printf(" "); 661 } 662 if (j < limit) { 663 printf("%02x", addr[j]); 664 } else { 665 printf(" "); 666 } 667 } 668 printf(" "); 669 for (j = i; j < limit; j++) { 670 if (j % OTHER_LEN == 0) { 671 printf(" "); 672 } 673 if (addr[j] < ' ') { 674 printf("."); 675 } else { 676 printf("%c", addr[j]); 677 } 678 } 679 } 680 printf("\n"); 681 } 682 683 void 684 full_dump_block_zero(partition_map_header *map) 685 { 686 Block0 *zp; 687 DDMap *m; 688 int i; 689 690 if (map == NULL) { 691 printf("No partition map exists\n"); 692 return; 693 } 694 695 if (map->misc == NULL) { 696 printf("No block zero\n"); 697 return; 698 } 699 zp = map->misc; 700 701 printf(" signature: 0x%x\n", zp->sbSig); 702 printf(" size of a block: %d\n", zp->sbBlkSize); 703 printf(" number of blocks: %"PRId32"\n", zp->sbBlkCount); 704 printf(" device type: 0x%x\n", zp->sbDevType); 705 printf(" device id: 0x%x\n", zp->sbDevId); 706 printf(" data: 0x%"PRIx32"\n", zp->sbData); 707 printf(" driver count: %d\n", zp->sbDrvrCount); 708 m = (DDMap *) zp->sbMap; 709 for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) { 710 if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) { 711 break; 712 } 713 printf(" driver %3u block: %"PRId32"\n", i+1, m[i].ddBlock); 714 printf(" size in blocks: %d\n", m[i].ddSize); 715 printf(" driver type: 0x%x\n", m[i].ddType); 716 } 717 printf("remainder of block -"); 718 dump_block((uint8_t *)(void *)&m[i].ddBlock, (&zp->sbMap[247]-((uint16_t *)(void *)&m[i].ddBlock))*2); 719 } 720 721 722 void 723 display_patches(partition_map *entry) 724 { 725 long long offset; 726 MEDIA m; 727 static uint8_t *patch_block; 728 PatchListPtr p; 729 PatchDescriptorPtr q; 730 uint8_t *next; 731 uint8_t *s; 732 int i; 733 734 offset = entry->data->dpme_pblock_start; 735 m = entry->the_map->m; 736 offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block; 737 if (patch_block == NULL) { 738 patch_block = (uint8_t *) malloc(PBLOCK_SIZE); 739 if (patch_block == NULL) { 740 error(errno, "can't allocate memory for patch block buffer"); 741 return; 742 } 743 } 744 if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) { 745 error(errno, "Can't read patch block"); 746 return; 747 } 748 p = (PatchListPtr) patch_block; 749 if (p->numPatchBlocks != 1) { 750 i = p->numPatchBlocks; 751 free(patch_block); 752 patch_block = (uint8_t *) malloc(PBLOCK_SIZE*i); 753 if (patch_block == NULL) { 754 error(errno, "can't allocate memory for patch blocks buffer"); 755 return; 756 } 757 s = patch_block + PBLOCK_SIZE*i; 758 while (i > 0) { 759 s -= PBLOCK_SIZE; 760 i -= 1; 761 if (read_media(m, offset+i, PBLOCK_SIZE, (char *)s) == 0) { 762 error(errno, "Can't read patch block %d", i); 763 return; 764 } 765 } 766 p = (PatchListPtr) patch_block; 767 } 768 printf("Patch list (%d entries)\n", p->numPatches); 769 q = p->thePatch; 770 for (i = 0; i < p->numPatches; i++) { 771 printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig); 772 printf(" version: %d.%d\n", q->majorVers, q->minorVers); 773 printf(" flags: 0x%"PRIx32"\n", q->flags); 774 printf(" offset: %"PRId32"\n", q->patchOffset); 775 printf(" size: %"PRId32"\n", q->patchSize); 776 printf(" CRC: 0x%"PRIx32"\n", q->patchCRC); 777 printf(" name: '%.*s'\n", q->patchName[0], &q->patchName[1]); 778 printf(" vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]); 779 next = ((uint8_t *)q) + q->patchDescriptorLen; 780 s = &q->patchVendor[q->patchVendor[0]+1]; 781 if (next > s) { 782 printf("remainder of entry -"); 783 dump_block(s, next-s); 784 } 785 q = (PatchDescriptorPtr)next; 786 } 787 } 788 789 int 790 get_max_type_string_length(partition_map_header *map) 791 { 792 partition_map * entry; 793 int max; 794 int length; 795 796 if (map == NULL) { 797 return 0; 798 } 799 800 max = 0; 801 802 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 803 length = strnlen(entry->data->dpme_type, DPISTRLEN); 804 if (length > max) { 805 max = length; 806 } 807 } 808 809 return max; 810 } 811 812 int 813 get_max_name_string_length(partition_map_header *map) 814 { 815 partition_map * entry; 816 int max; 817 int length; 818 819 if (map == NULL) { 820 return 0; 821 } 822 823 max = 0; 824 825 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 826 length = strnlen(entry->data->dpme_name, DPISTRLEN); 827 if (length > max) { 828 max = length; 829 } 830 831 if (fflag) { 832 if (entry->HFS_name == NULL) { 833 length = 0; 834 } else { 835 length = strlen(entry->HFS_name) + 2; 836 } 837 if (length > max) { 838 max = length; 839 } 840 } 841 } 842 843 return max; 844 } 845 846 int 847 get_max_base_or_length(partition_map_header *map) 848 { 849 partition_map * entry; 850 uint32_t max; 851 852 if (map == NULL) { 853 return 0; 854 } 855 856 max = 0; 857 858 for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) { 859 if (entry->data->dpme_pblock_start > max) { 860 max = entry->data->dpme_pblock_start; 861 } 862 if (entry->data->dpme_pblocks > max) { 863 max = entry->data->dpme_pblocks; 864 } 865 if (entry->data->dpme_lblock_start > max) { 866 max = entry->data->dpme_lblock_start; 867 } 868 if (entry->data->dpme_lblocks > max) { 869 max = entry->data->dpme_lblocks; 870 } 871 } 872 873 return max; 874 } 875 876 void 877 adjust_value_and_compute_prefix(double *value, int *prefix) 878 { 879 double bytes; 880 int multiplier; 881 882 bytes = *value; 883 if (bytes < 1024.0) { 884 multiplier = ' '; 885 } else { 886 bytes = bytes / 1024.0; 887 if (bytes < 1024.0) { 888 multiplier = 'K'; 889 } else { 890 bytes = bytes / 1024.0; 891 if (bytes < 1024.0) { 892 multiplier = 'M'; 893 } else { 894 bytes = bytes / 1024.0; 895 if (bytes < 1024.0) { 896 multiplier = 'G'; 897 } else { 898 bytes = bytes / 1024.0; 899 multiplier = 'T'; 900 } 901 } 902 } 903 } 904 *value = bytes; 905 *prefix = multiplier; 906 } 907