2 // dump.c - dumping partition maps
4 // Written by Eryk Vershen
8 * Copyright 1996,1997,1998 by Apple Computer, Inc.
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.
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.
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.
31 // for malloc() & free()
56 #error Change in strlen in partition entries! Fix constants
59 #define get_align_long(x) (*(x))
65 typedef struct names
{
71 typedef unsigned long OSType
;
74 typedef struct PatchDescriptor
{
76 unsigned short majorVers
;
77 unsigned short minorVers
;
79 unsigned long patchOffset
;
80 unsigned long patchSize
;
81 unsigned long patchCRC
;
82 unsigned long patchDescriptorLen
;
83 unsigned char patchName
[33];
84 unsigned char patchVendor
[1];
86 typedef PatchDescriptor
* PatchDescriptorPtr
;
88 typedef struct PatchList
{
89 unsigned short numPatchBlocks
; // number of disk blocks to hold the patch list
90 unsigned short numPatches
; // number of patches in list
91 PatchDescriptor thePatch
[1];
93 typedef PatchList
*PatchListPtr
;
100 {"Drvr", "Apple_Driver"},
101 {"Drv4", "Apple_Driver43"},
102 {"Free", "Apple_Free"},
103 {"Patc", "Apple_Patches"},
104 {" HFS", "Apple_HFS"},
105 {" MFS", "Apple_MFS"},
106 {"PDOS", "Apple_PRODOS"},
107 {"junk", "Apple_Scratch"},
108 {"unix", "Apple_UNIX_SVR2"},
109 {" map", "Apple_partition_map"},
113 const char * kStringEmpty
= "";
114 const char * kStringNot
= " not";
120 int aflag
= AFLAG_DEFAULT
; /* abbreviate partition types */
121 int pflag
= PFLAG_DEFAULT
; /* show physical limits of partition */
122 int fflag
= FFLAG_DEFAULT
; /* show HFS volume names */
126 // Forward declarations
128 void adjust_value_and_compute_prefix(double *value
, int *prefix
);
129 void dump_block_zero(partition_map_header
*map
);
130 void dump_partition_entry(partition_map
*entry
, int type_length
, int name_length
, int digits
);
131 int get_max_base_or_length(partition_map_header
*map
);
132 int get_max_name_string_length(partition_map_header
*map
);
133 int get_max_type_string_length(partition_map_header
*map
);
142 partition_map_header
*map
;
145 map
= open_partition_map(name
, &junk
, 0);
147 //error(-1, "No partition map in '%s'", name);
151 dump_partition_map(map
, 1);
153 close_partition_map(map
);
160 dump_block_zero(partition_map_header
*map
)
170 if (p
->sbSig
!= BLOCK0_SIGNATURE
) {
174 value
= ((double)p
->sbBlkCount
) * p
->sbBlkSize
;
175 adjust_value_and_compute_prefix(&value
, &prefix
);
176 printf("\nDevice block size=%u, Number of Blocks=%lu (%1.1f%c)\n",
177 p
->sbBlkSize
, p
->sbBlkCount
, value
, prefix
);
179 printf("DeviceType=0x%x, DeviceId=0x%x\n",
180 p
->sbDevType
, p
->sbDevId
);
181 if (p
->sbDrvrCount
> 0) {
182 printf("Drivers-\n");
183 m
= (DDMap
*) p
->sbMap
;
184 for (i
= 0; i
< p
->sbDrvrCount
; i
++) {
185 printf("%u: %3u @ %lu, ", i
+1,
186 m
[i
].ddSize
, get_align_long(&m
[i
].ddBlock
));
187 if (map
->logical_block
!= p
->sbBlkSize
) {
188 t
= (m
[i
].ddSize
* p
->sbBlkSize
) / map
->logical_block
;
190 t
= (get_align_long(&m
[i
].ddBlock
) * p
->sbBlkSize
)
191 / map
->logical_block
;
194 printf("type=0x%x\n", m
[i
].ddType
);
202 dump_partition_map(partition_map_header
*map
, int disk_order
)
204 partition_map
* entry
;
211 bad_input("No partition map exists");
214 alternate
= get_linux_name(map
->name
);
216 printf("\nPartition map (with %d byte blocks) on '%s' (%s)\n",
217 map
->logical_block
, map
->name
, alternate
);
220 printf("\nPartition map (with %d byte blocks) on '%s'\n",
221 map
->logical_block
, map
->name
);
224 digits
= number_of_digits(get_max_base_or_length(map
));
231 max_type_length
= get_max_type_string_length(map
);
232 if (max_type_length
< 4) {
236 max_name_length
= get_max_name_string_length(map
);
237 if (max_name_length
< 6) {
240 printf(" #: %*s %-*s %*s %-*s ( size )\n",
241 max_type_length
, "type",
242 max_name_length
, "name",
243 digits
, "length", digits
, "base");
246 for (entry
= map
->disk_order
; entry
!= NULL
;
247 entry
= entry
->next_on_disk
) {
249 dump_partition_entry(entry
, max_type_length
, max_name_length
, digits
);
252 for (entry
= map
->base_order
; entry
!= NULL
;
253 entry
= entry
->next_by_base
) {
255 dump_partition_entry(entry
, max_type_length
, max_name_length
, digits
);
258 dump_block_zero(map
);
263 dump_partition_entry(partition_map
*entry
, int type_length
, int name_length
, int digits
)
265 partition_map_header
*map
;
278 map
= entry
->the_map
;
280 driver
= entry
->contains_driver
? '*': ' ';
283 for (j
= 0; plist
[j
].abbr
!= 0; j
++) {
284 if (strcmp(p
->dpme_type
, plist
[j
].full
) == 0) {
289 printf("%2ld: %.4s", entry
->disk_address
, s
);
291 printf("%2ld: %*.32s", entry
->disk_address
, type_length
, p
->dpme_type
);
294 buf
= (char *) malloc(name_length
+1);
295 if (entry
->HFS_name
== NULL
|| fflag
== 0) {
296 strncpy(buf
, p
->dpme_name
, name_length
);
297 buf
[name_length
] = 0;
299 snprintf(buf
, name_length
+ 1, "\"%s\"", entry
->HFS_name
);
301 printf("%c%-*.32s ", driver
, name_length
, buf
);
304 switch (entry->HFS_kind) {
305 case kHFS_std: kind = 'h'; break;
306 case kHFS_embed: kind = 'e'; break;
307 case kHFS_plus: kind = '+'; break;
309 case kHFS_not: kind = ' '; break;
315 printf("%*lu ", digits
, p
->dpme_pblocks
);
316 size
= p
->dpme_pblocks
;
317 } else if (p
->dpme_lblocks
+ p
->dpme_lblock_start
!= p
->dpme_pblocks
) {
318 printf("%*lu+", digits
, p
->dpme_lblocks
);
319 size
= p
->dpme_lblocks
;
320 } else if (p
->dpme_lblock_start
!= 0) {
321 printf("%*lu ", digits
, p
->dpme_lblocks
);
322 size
= p
->dpme_lblocks
;
324 printf("%*lu ", digits
, p
->dpme_pblocks
);
325 size
= p
->dpme_pblocks
;
327 if (pflag
|| p
->dpme_lblock_start
== 0) {
328 printf("@ %-*lu", digits
, p
->dpme_pblock_start
);
330 printf("@~%-*lu", digits
, p
->dpme_pblock_start
+ p
->dpme_lblock_start
);
333 bytes
= ((double)size
) * map
->logical_block
;
334 adjust_value_and_compute_prefix(&bytes
, &j
);
335 if (j
!= ' ' && j
!= 'K') {
336 printf(" (%#5.1f%c)", bytes
, j
);
340 // Old A/UX fields that no one pays attention to anymore.
341 bp
= (BZB
*) (p
->dpme_bzb
);
343 if (bp
->bzb_magic
== BZBMAGIC
) {
344 switch (bp
->bzb_type
) {
354 if (bzb_root_get(bp
) != 0) {
355 if (bzb_usr_get(bp
) != 0) {
361 } else if (bzb_usr_get(bp
) != 0) {
369 if (bzb_slice_get(bp
) != 0) {
370 printf(" s%1ld %4s", bzb_slice_get(bp
)-1, s
);
372 printf(" S%1d %4s", j
, s
);
376 if (bzb_crit_get(bp
) != 0) {
377 printf(" K%1d", bp
->bzb_cluster
);
381 printf(" k%1d", bp
->bzb_cluster
);
383 if (bp
->bzb_mount_point
[0] != 0) {
384 printf(" %.64s", bp
->bzb_mount_point
);
401 data
= (DPME
*) malloc(PBLOCK_SIZE
);
403 error(errno
, "can't allocate memory for try buffer");
407 for (iter
= first_media_kind(&mark
); iter
!= 0; iter
= next_media_kind(&mark
)) {
409 while ((name
= step_media_iterator(iter
)) != 0) {
411 if ((m
= open_pathname_as_media(name
, O_RDONLY
)) == 0) {
412 #if defined(__linux__) || defined(__unix__)
413 error(errno
, "can't open file '%s'", name
);
423 delete_media_iterator(iter
);
431 show_data_structures(partition_map_header
*map
)
437 partition_map
* entry
;
443 printf("No partition map exists\n");
447 printf("map %d blocks out of %d, media %lu blocks (%d byte blocks)\n",
448 map
->blocks_in_map
, map
->maximum_in_map
,
449 map
->media_size
, map
->logical_block
);
450 printf("Map is%s writable", (map
->writable
)?kStringEmpty
:kStringNot
);
451 printf(", but%s changed", (map
->changed
)?kStringEmpty
:kStringNot
);
452 printf(" and has%s been written\n", (map
->written
)?kStringEmpty
:kStringNot
);
455 if (map
->misc
== NULL
) {
456 printf("No block zero\n");
461 printf("signature 0x%x", zp
->sbSig
);
462 if (zp
->sbSig
== BLOCK0_SIGNATURE
) {
465 printf(" should be 0x%x\n", BLOCK0_SIGNATURE
);
467 printf("Block size=%u, Number of Blocks=%lu\n",
468 zp
->sbBlkSize
, zp
->sbBlkCount
);
469 printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%lx\n",
470 zp
->sbDevType
, zp
->sbDevId
, zp
->sbData
);
471 if (zp
->sbDrvrCount
== 0) {
472 printf("No drivers\n");
474 printf("%u driver%s-\n", zp
->sbDrvrCount
,
475 (zp
->sbDrvrCount
>1)?"s":kStringEmpty
);
476 m
= (DDMap
*) zp
->sbMap
;
477 for (i
= 0; i
< zp
->sbDrvrCount
; i
++) {
478 printf("%u: @ %lu for %u, type=0x%x\n", i
+1,
479 get_align_long(&m
[i
].ddBlock
),
480 m
[i
].ddSize
, m
[i
].ddType
);
487 u32 dpme_boot_args[32] ;
488 u32 dpme_reserved_3[62] ;
490 printf(" #: type length base "
491 "flags (logical)\n");
492 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
494 printf("%2ld: %20.32s ",
495 entry
->disk_address
, p
->dpme_type
);
496 printf("%7lu @ %-7lu ", p
->dpme_pblocks
, p
->dpme_pblock_start
);
497 printf("%c%c%c%c%c%c%c%c%c%c%c%c ",
498 (dpme_valid_get(p
))?'V':'.',
499 (dpme_allocated_get(p
))?'A':'.',
500 (dpme_in_use_get(p
))?'I':'.',
501 (dpme_bootable_get(p
))?'B':'.',
502 (dpme_readable_get(p
))?'R':'.',
503 (dpme_writable_get(p
))?'W':'.',
504 (dpme_os_pic_code_get(p
))?'P':'.',
505 (dpme_os_specific_2_get(p
))?'2':'.',
506 (dpme_chainable_get(p
))?'C':'.',
507 (dpme_diskdriver_get(p
))?'D':'.',
508 (bitfield_get(p
->dpme_flags
, 30, 1))?'M':'.',
509 (bitfield_get(p
->dpme_flags
, 31, 1))?'X':'.');
510 if (p
->dpme_lblock_start
!= 0 || p
->dpme_pblocks
!= p
->dpme_lblocks
) {
511 printf("(%lu @ %lu)", p
->dpme_lblocks
, p
->dpme_lblock_start
);
516 printf(" #: booter bytes load_address "
517 "goto_address checksum processor\n");
518 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
520 printf("%2ld: ", entry
->disk_address
);
521 printf("%7lu ", p
->dpme_boot_block
);
522 printf("%7lu ", p
->dpme_boot_bytes
);
523 printf("%8lx ", (u32
)p
->dpme_load_addr
);
524 printf("%8lx ", (u32
)p
->dpme_load_addr_2
);
525 printf("%8lx ", (u32
)p
->dpme_goto_addr
);
526 printf("%8lx ", (u32
)p
->dpme_goto_addr_2
);
527 printf("%8lx ", p
->dpme_checksum
);
528 printf("%.32s", p
->dpme_process_id
);
535 printf(" #: type RU *slice mount_point (A/UX only fields)\n");
536 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
538 printf("%2ld: ", entry
->disk_address
);
540 bp
= (BZB
*) (p
->dpme_bzb
);
542 if (bp
->bzb_magic
== BZBMAGIC
) {
543 switch (bp
->bzb_type
) {
554 if (bzb_root_get(bp
) != 0) {
556 } else if (bzb_usr_get(bp
) != 0) {
563 (bzb_root_get(bp
))?'R':' ',
564 (bzb_usr_get(bp
))?'U':' ');
565 if (bzb_slice_get(bp
) != 0) {
566 printf(" %2ld", bzb_slice_get(bp
)-1);
572 if (bp
->bzb_mount_point
[0] != 0) {
573 printf(" %.64s", bp
->bzb_mount_point
);
582 full_dump_partition_entry(partition_map_header
*map
, int ix
)
589 cur
= find_entry_by_disk_address(ix
, map
);
591 printf("No such partition\n");
596 printf(" signature: 0x%x\n", p
->dpme_signature
);
597 printf(" reserved1: 0x%x\n", p
->dpme_reserved_1
);
598 printf(" number of map entries: %ld\n", p
->dpme_map_entries
);
599 printf(" physical start: %10lu length: %10lu\n", p
->dpme_pblock_start
, p
->dpme_pblocks
);
600 printf(" logical start: %10lu length: %10lu\n", p
->dpme_lblock_start
, p
->dpme_lblocks
);
602 printf(" flags: 0x%lx\n", (u32
)p
->dpme_flags
);
604 if (dpme_valid_get(p
)) printf("valid ");
605 if (dpme_allocated_get(p
)) printf("alloc ");
606 if (dpme_in_use_get(p
)) printf("in-use ");
607 if (dpme_bootable_get(p
)) printf("boot ");
608 if (dpme_readable_get(p
)) printf("read ");
609 if (dpme_writable_get(p
)) printf("write ");
610 if (dpme_os_pic_code_get(p
)) printf("pic ");
611 t
= p
->dpme_flags
>> 7;
612 for (i
= 7; i
<= 31; i
++) {
620 printf(" name: '%.32s'\n", p
->dpme_name
);
621 printf(" type: '%.32s'\n", p
->dpme_type
);
623 printf(" boot start block: %10lu\n", p
->dpme_boot_block
);
624 printf("boot length (in bytes): %10lu\n", p
->dpme_boot_bytes
);
625 printf(" load address: 0x%08lx 0x%08lx\n",
626 (u32
)p
->dpme_load_addr
, (u32
)p
->dpme_load_addr_2
);
627 printf(" start address: 0x%08lx 0x%08lx\n",
628 (u32
)p
->dpme_goto_addr
, (u32
)p
->dpme_goto_addr_2
);
629 printf(" checksum: 0x%08lx\n", p
->dpme_checksum
);
630 printf(" processor: '%.32s'\n", p
->dpme_process_id
);
631 printf("boot args field -");
632 dump_block((unsigned char *)p
->dpme_boot_args
, 32*4);
633 printf("dpme_reserved_3 -");
634 dump_block((unsigned char *)p
->dpme_reserved_3
, 62*4);
639 dump_block(unsigned char *addr
, int len
)
649 for (i
= 0; i
< len
; i
= limit
) {
650 limit1
= i
+ LINE_LEN
;
656 printf("\n%03x: ", i
);
657 for (j
= i
; j
< limit1
; j
++) {
658 if (j
% UNIT_LEN
== 0) {
662 printf("%02x", addr
[j
]);
668 for (j
= i
; j
< limit
; j
++) {
669 if (j
% OTHER_LEN
== 0) {
675 printf("%c", addr
[j
]);
683 full_dump_block_zero(partition_map_header
*map
)
690 printf("No partition map exists\n");
694 if (map
->misc
== NULL
) {
695 printf("No block zero\n");
700 printf(" signature: 0x%x\n", zp
->sbSig
);
701 printf(" size of a block: %d\n", zp
->sbBlkSize
);
702 printf(" number of blocks: %ld\n", zp
->sbBlkCount
);
703 printf(" device type: 0x%x\n", zp
->sbDevType
);
704 printf(" device id: 0x%x\n", zp
->sbDevId
);
705 printf(" data: 0x%lx\n", zp
->sbData
);
706 printf(" driver count: %d\n", zp
->sbDrvrCount
);
707 m
= (DDMap
*) zp
->sbMap
;
708 for (i
= 0; &m
[i
].ddType
< &zp
->sbMap
[247]; i
++) {
709 if (m
[i
].ddBlock
== 0 && m
[i
].ddSize
== 0 && m
[i
].ddType
== 0) {
712 printf(" driver %3u block: %ld\n", i
+1, m
[i
].ddBlock
);
713 printf(" size in blocks: %d\n", m
[i
].ddSize
);
714 printf(" driver type: 0x%x\n", m
[i
].ddType
);
716 printf("remainder of block -");
717 dump_block((unsigned char *)(void *)&m
[i
].ddBlock
, (&zp
->sbMap
[247]-((unsigned short *)(void *)&m
[i
].ddBlock
))*2);
722 display_patches(partition_map
*entry
)
726 static unsigned char *patch_block
;
728 PatchDescriptorPtr q
;
733 offset
= entry
->data
->dpme_pblock_start
;
734 m
= entry
->the_map
->m
;
735 offset
= ((long long) entry
->data
->dpme_pblock_start
) * entry
->the_map
->logical_block
;
736 if (patch_block
== NULL
) {
737 patch_block
= (unsigned char *) malloc(PBLOCK_SIZE
);
738 if (patch_block
== NULL
) {
739 error(errno
, "can't allocate memory for patch block buffer");
743 if (read_media(m
, (long long)offset
, PBLOCK_SIZE
, (char *)patch_block
) == 0) {
744 error(errno
, "Can't read patch block");
747 p
= (PatchListPtr
) patch_block
;
748 if (p
->numPatchBlocks
!= 1) {
749 i
= p
->numPatchBlocks
;
751 patch_block
= (unsigned char *) malloc(PBLOCK_SIZE
*i
);
752 if (patch_block
== NULL
) {
753 error(errno
, "can't allocate memory for patch blocks buffer");
756 s
= patch_block
+ PBLOCK_SIZE
*i
;
760 if (read_media(m
, offset
+i
, PBLOCK_SIZE
, (char *)s
) == 0) {
761 error(errno
, "Can't read patch block %d", i
);
765 p
= (PatchListPtr
) patch_block
;
767 printf("Patch list (%d entries)\n", p
->numPatches
);
769 for (i
= 0; i
< p
->numPatches
; i
++) {
770 printf("%2d signature: '%.4s'\n", i
+1, (char *)&q
->patchSig
);
771 printf(" version: %d.%d\n", q
->majorVers
, q
->minorVers
);
772 printf(" flags: 0x%lx\n", q
->flags
);
773 printf(" offset: %ld\n", q
->patchOffset
);
774 printf(" size: %ld\n", q
->patchSize
);
775 printf(" CRC: 0x%lx\n", q
->patchCRC
);
776 printf(" name: '%.*s'\n", q
->patchName
[0], &q
->patchName
[1]);
777 printf(" vendor: '%.*s'\n", q
->patchVendor
[0], &q
->patchVendor
[1]);
778 next
= ((unsigned char *)q
) + q
->patchDescriptorLen
;
779 s
= &q
->patchVendor
[q
->patchVendor
[0]+1];
781 printf("remainder of entry -");
782 dump_block(s
, next
-s
);
784 q
= (PatchDescriptorPtr
)next
;
789 get_max_type_string_length(partition_map_header
*map
)
791 partition_map
* entry
;
801 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
802 length
= strnlen(entry
->data
->dpme_type
, DPISTRLEN
);
812 get_max_name_string_length(partition_map_header
*map
)
814 partition_map
* entry
;
824 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
825 length
= strnlen(entry
->data
->dpme_name
, DPISTRLEN
);
831 if (entry
->HFS_name
== NULL
) {
834 length
= strlen(entry
->HFS_name
) + 2;
846 get_max_base_or_length(partition_map_header
*map
)
848 partition_map
* entry
;
857 for (entry
= map
->disk_order
; entry
!= NULL
; entry
= entry
->next_on_disk
) {
858 if (entry
->data
->dpme_pblock_start
> max
) {
859 max
= entry
->data
->dpme_pblock_start
;
861 if (entry
->data
->dpme_pblocks
> max
) {
862 max
= entry
->data
->dpme_pblocks
;
864 if (entry
->data
->dpme_lblock_start
> max
) {
865 max
= entry
->data
->dpme_lblock_start
;
867 if (entry
->data
->dpme_lblocks
> max
) {
868 max
= entry
->data
->dpme_lblocks
;
876 adjust_value_and_compute_prefix(double *value
, int *prefix
)
882 if (bytes
< 1024.0) {
885 bytes
= bytes
/ 1024.0;
886 if (bytes
< 1024.0) {
889 bytes
= bytes
/ 1024.0;
890 if (bytes
< 1024.0) {
893 bytes
= bytes
/ 1024.0;
894 if (bytes
< 1024.0) {
897 bytes
= bytes
/ 1024.0;
904 *prefix
= multiplier
;