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