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