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
dump(char * name)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
dump_block_zero(partition_map_header * map)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
dump_partition_map(partition_map_header * map,int disk_order)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
dump_partition_entry(partition_map * entry,int type_length,int name_length,int digits)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
list_all_disks(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
show_data_structures(partition_map_header * map)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
full_dump_partition_entry(partition_map_header * map,int ix)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
dump_block(uint8_t * addr,int len)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
full_dump_block_zero(partition_map_header * map)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
display_patches(partition_map * entry)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
get_max_type_string_length(partition_map_header * map)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
get_max_name_string_length(partition_map_header * map)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
get_max_base_or_length(partition_map_header * map)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
adjust_value_and_compute_prefix(double * value,int * prefix)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