xref: /netbsd-src/external/bsd/pdisk/dist/dump.c (revision 48a628ae0434c4247b560ad8f2eb1dc06d0dd070)
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