xref: /openbsd/sbin/pdisk/dump.c (revision 94d20309)
1*94d20309Skrw /*	$OpenBSD: dump.c,v 1.28 2016/01/17 16:44:01 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 
47f42746d7Skrw #include "file_media.h"
48dce63815Sdrahn #include "dump.h"
49dce63815Sdrahn #include "io.h"
50dce63815Sdrahn 
51dce63815Sdrahn 
52dce63815Sdrahn //
53dce63815Sdrahn // Defines
54dce63815Sdrahn //
55dce63815Sdrahn #define get_align_long(x)	(*(x))
56dce63815Sdrahn 
57dce63815Sdrahn 
58dce63815Sdrahn //
59dce63815Sdrahn // Types
60dce63815Sdrahn //
61b42d9302Smartin 
62*94d20309Skrw struct patchdescriptor {
6317e07d8fSkrw     unsigned long	patchSig;
64b42d9302Smartin     unsigned short	majorVers;
65b42d9302Smartin     unsigned short	minorVers;
66b42d9302Smartin     unsigned long	flags;
67b42d9302Smartin     unsigned long	patchOffset;
68b42d9302Smartin     unsigned long	patchSize;
69b42d9302Smartin     unsigned long	patchCRC;
70b42d9302Smartin     unsigned long	patchDescriptorLen;
71b42d9302Smartin     unsigned char	patchName[33];
72b42d9302Smartin     unsigned char	patchVendor[1];
73*94d20309Skrw };
74b42d9302Smartin 
75*94d20309Skrw struct patchlist {
76b42d9302Smartin     unsigned short numPatchBlocks;	// number of disk blocks to hold the patch list
77b42d9302Smartin     unsigned short numPatches;		// number of patches in list
78*94d20309Skrw     struct patchdescriptor thePatch[1];
79*94d20309Skrw };
80b42d9302Smartin 
81dce63815Sdrahn 
82dce63815Sdrahn //
83dce63815Sdrahn // Global Constants
84dce63815Sdrahn //
85dce63815Sdrahn 
86dce63815Sdrahn const char * kStringEmpty	= "";
87dce63815Sdrahn const char * kStringNot		= " not";
88dce63815Sdrahn 
89dce63815Sdrahn 
90dce63815Sdrahn //
91dce63815Sdrahn // Global Variables
92dce63815Sdrahn //
93dce63815Sdrahn 
94dce63815Sdrahn 
95dce63815Sdrahn //
96dce63815Sdrahn // Forward declarations
97dce63815Sdrahn //
98dce63815Sdrahn void adjust_value_and_compute_prefix(double *value, int *prefix);
99dce63815Sdrahn void dump_block_zero(partition_map_header *map);
100dce63815Sdrahn void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits);
101dce63815Sdrahn int get_max_base_or_length(partition_map_header *map);
102dce63815Sdrahn int get_max_name_string_length(partition_map_header *map);
103dce63815Sdrahn int get_max_type_string_length(partition_map_header *map);
104dce63815Sdrahn 
105dce63815Sdrahn 
106dce63815Sdrahn //
107dce63815Sdrahn // Routines
108dce63815Sdrahn //
109dce63815Sdrahn int
110dce63815Sdrahn dump(char *name)
111dce63815Sdrahn {
112dce63815Sdrahn     partition_map_header *map;
113dce63815Sdrahn     int junk;
114dce63815Sdrahn 
1155d0b0825Skrw     map = open_partition_map(name, &junk);
116dce63815Sdrahn     if (map == NULL) {
117dce63815Sdrahn 	return 0;
118dce63815Sdrahn     }
119dce63815Sdrahn 
120dce63815Sdrahn     dump_partition_map(map, 1);
121dce63815Sdrahn 
122dce63815Sdrahn     close_partition_map(map);
123dce63815Sdrahn 
124dce63815Sdrahn     return 1;
125dce63815Sdrahn }
126dce63815Sdrahn 
127dce63815Sdrahn 
128dce63815Sdrahn void
129dce63815Sdrahn dump_block_zero(partition_map_header *map)
130dce63815Sdrahn {
13171bd5f9cSkrw     struct block0 *p;
13270060700Skrw     struct ddmap *m;
133dce63815Sdrahn     int i;
134dce63815Sdrahn     double value;
135dce63815Sdrahn     int prefix;
136b42d9302Smartin     long t;
137dce63815Sdrahn 
138dce63815Sdrahn     p = map->misc;
139dce63815Sdrahn     if (p->sbSig != BLOCK0_SIGNATURE) {
140dce63815Sdrahn 	return;
141dce63815Sdrahn     }
142dce63815Sdrahn 
143dce63815Sdrahn     value = ((double)p->sbBlkCount) * p->sbBlkSize;
144dce63815Sdrahn     adjust_value_and_compute_prefix(&value, &prefix);
145dce63815Sdrahn     printf("\nDevice block size=%u, Number of Blocks=%lu (%1.1f%c)\n",
146dce63815Sdrahn 	    p->sbBlkSize, p->sbBlkCount, value, prefix);
147dce63815Sdrahn 
148dce63815Sdrahn     printf("DeviceType=0x%x, DeviceId=0x%x\n",
149dce63815Sdrahn 	    p->sbDevType, p->sbDevId);
150dce63815Sdrahn     if (p->sbDrvrCount > 0) {
151dce63815Sdrahn 	printf("Drivers-\n");
15270060700Skrw 	m = (struct ddmap *) p->sbMap;
153dce63815Sdrahn 	for (i = 0; i < p->sbDrvrCount; i++) {
154b42d9302Smartin 	    printf("%u: %3u @ %lu, ", i+1,
155b42d9302Smartin 		    m[i].ddSize, get_align_long(&m[i].ddBlock));
156b42d9302Smartin 	    if (map->logical_block != p->sbBlkSize) {
157b42d9302Smartin 		t = (m[i].ddSize * p->sbBlkSize) / map->logical_block;
158b42d9302Smartin 		printf("(%lu@", t);
159b42d9302Smartin 		t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize)
160b42d9302Smartin 			/ map->logical_block;
161b42d9302Smartin 		printf("%lu)  ", t);
162b42d9302Smartin 	    }
163b42d9302Smartin 	    printf("type=0x%x\n", m[i].ddType);
164dce63815Sdrahn 	}
165dce63815Sdrahn     }
166dce63815Sdrahn     printf("\n");
167dce63815Sdrahn }
168dce63815Sdrahn 
169dce63815Sdrahn 
170dce63815Sdrahn void
171dce63815Sdrahn dump_partition_map(partition_map_header *map, int disk_order)
172dce63815Sdrahn {
173dce63815Sdrahn     partition_map * entry;
174dce63815Sdrahn     int max_type_length;
175dce63815Sdrahn     int max_name_length;
176dce63815Sdrahn     int digits;
177dce63815Sdrahn 
178dce63815Sdrahn     if (map == NULL) {
179dce63815Sdrahn 	bad_input("No partition map exists");
180dce63815Sdrahn 	return;
181dce63815Sdrahn     }
182dce63815Sdrahn     printf("\nPartition map (with %d byte blocks) on '%s'\n",
183dce63815Sdrahn 	map->logical_block, map->name);
184dce63815Sdrahn 
185dce63815Sdrahn     digits = number_of_digits(get_max_base_or_length(map));
186dce63815Sdrahn     if (digits < 6) {
187dce63815Sdrahn 	digits = 6;
188dce63815Sdrahn     }
189dce63815Sdrahn     max_type_length = get_max_type_string_length(map);
190dce63815Sdrahn     if (max_type_length < 4) {
191dce63815Sdrahn         max_type_length = 4;
192dce63815Sdrahn     }
193dce63815Sdrahn     max_name_length = get_max_name_string_length(map);
194dce63815Sdrahn     if (max_name_length < 6) {
195dce63815Sdrahn 	max_name_length = 6;
196dce63815Sdrahn     }
197dce63815Sdrahn     printf(" #: %*s %-*s %*s   %-*s ( size )\n",
198dce63815Sdrahn 	    max_type_length, "type",
199dce63815Sdrahn 	    max_name_length, "name",
200dce63815Sdrahn 	    digits, "length", digits, "base");
201dce63815Sdrahn 
202dce63815Sdrahn     if (disk_order) {
203dce63815Sdrahn 	for (entry = map->disk_order; entry != NULL;
204dce63815Sdrahn 		entry = entry->next_on_disk) {
205dce63815Sdrahn 
206dce63815Sdrahn 	    dump_partition_entry(entry, max_type_length, max_name_length, digits);
207dce63815Sdrahn 	}
208dce63815Sdrahn     } else {
209dce63815Sdrahn 	for (entry = map->base_order; entry != NULL;
210dce63815Sdrahn 		entry = entry->next_by_base) {
211dce63815Sdrahn 
212dce63815Sdrahn 	    dump_partition_entry(entry, max_type_length, max_name_length, digits);
213dce63815Sdrahn 	}
214dce63815Sdrahn     }
215dce63815Sdrahn     dump_block_zero(map);
216dce63815Sdrahn }
217dce63815Sdrahn 
218dce63815Sdrahn 
219dce63815Sdrahn void
220dce63815Sdrahn dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits)
221dce63815Sdrahn {
222dce63815Sdrahn     partition_map_header *map;
223dce63815Sdrahn     int j;
2246521004eSkrw     struct dpme *p;
225dce63815Sdrahn     u32 size;
226dce63815Sdrahn     double bytes;
22777a25ee3Sjasper     int driver;
228b42d9302Smartin     char *buf;
229dce63815Sdrahn 
230dce63815Sdrahn     map = entry->the_map;
231dce63815Sdrahn     p = entry->data;
232dce63815Sdrahn     driver = entry->contains_driver? '*': ' ';
233b42d9302Smartin     printf("%2ld: %*.32s", entry->disk_address, type_length, p->dpme_type);
234dce63815Sdrahn 
2355ae94ef8Sderaadt     buf = malloc(name_length+1);
236b42d9302Smartin     strncpy(buf, p->dpme_name, name_length);
237b42d9302Smartin     buf[name_length] = 0;
238b42d9302Smartin     printf("%c%-*.32s ", driver, name_length, buf);
239b42d9302Smartin     free(buf);
240b42d9302Smartin 
2417446d16eSkrw     if (p->dpme_lblocks + p->dpme_lblock_start != p->dpme_pblocks) {
242dce63815Sdrahn 	printf("%*lu+", digits, p->dpme_lblocks);
243dce63815Sdrahn 	size = p->dpme_lblocks;
244dce63815Sdrahn     } else if (p->dpme_lblock_start != 0) {
245dce63815Sdrahn 	printf("%*lu ", digits, p->dpme_lblocks);
246dce63815Sdrahn 	size = p->dpme_lblocks;
247dce63815Sdrahn     } else {
248dce63815Sdrahn 	printf("%*lu ", digits, p->dpme_pblocks);
249dce63815Sdrahn 	size = p->dpme_pblocks;
250dce63815Sdrahn     }
2517446d16eSkrw     if (p->dpme_lblock_start == 0) {
252dce63815Sdrahn 	printf("@ %-*lu", digits, p->dpme_pblock_start);
253dce63815Sdrahn     } else {
254dce63815Sdrahn 	printf("@~%-*lu", digits, p->dpme_pblock_start + p->dpme_lblock_start);
255dce63815Sdrahn     }
256dce63815Sdrahn 
257dce63815Sdrahn     bytes = ((double)size) * map->logical_block;
258dce63815Sdrahn     adjust_value_and_compute_prefix(&bytes, &j);
259dce63815Sdrahn     if (j != ' ' && j != 'K') {
260dce63815Sdrahn 	printf(" (%#5.1f%c)", bytes, j);
261dce63815Sdrahn     }
262dce63815Sdrahn 
263dce63815Sdrahn     printf("\n");
264dce63815Sdrahn }
265dce63815Sdrahn 
266dce63815Sdrahn 
267dce63815Sdrahn void
268dce63815Sdrahn show_data_structures(partition_map_header *map)
269dce63815Sdrahn {
27071bd5f9cSkrw     struct block0 *zp;
27170060700Skrw     struct ddmap *m;
272dce63815Sdrahn     int i;
273dce63815Sdrahn     partition_map * entry;
2746521004eSkrw     struct dpme *p;
275dce63815Sdrahn 
276dce63815Sdrahn     if (map == NULL) {
277dce63815Sdrahn 	printf("No partition map exists\n");
278dce63815Sdrahn 	return;
279dce63815Sdrahn     }
280dce63815Sdrahn     printf("Header:\n");
281dce63815Sdrahn     printf("map %d blocks out of %d,  media %lu blocks (%d byte blocks)\n",
282dce63815Sdrahn 	    map->blocks_in_map, map->maximum_in_map,
283dce63815Sdrahn 	    map->media_size, map->logical_block);
284b42d9302Smartin     printf("Map is%s writable", (map->writable)?kStringEmpty:kStringNot);
285b42d9302Smartin     printf(", but%s changed", (map->changed)?kStringEmpty:kStringNot);
286b42d9302Smartin     printf(" and has%s been written\n", (map->written)?kStringEmpty:kStringNot);
287dce63815Sdrahn     printf("\n");
288dce63815Sdrahn 
289dce63815Sdrahn     if (map->misc == NULL) {
290dce63815Sdrahn 	printf("No block zero\n");
291dce63815Sdrahn     } else {
292dce63815Sdrahn 	zp = map->misc;
293dce63815Sdrahn 
294dce63815Sdrahn 	printf("Block0:\n");
295dce63815Sdrahn 	printf("signature 0x%x", zp->sbSig);
296dce63815Sdrahn 	if (zp->sbSig == BLOCK0_SIGNATURE) {
297dce63815Sdrahn 	    printf("\n");
298dce63815Sdrahn 	} else {
299dce63815Sdrahn 	    printf(" should be 0x%x\n", BLOCK0_SIGNATURE);
300dce63815Sdrahn 	}
301dce63815Sdrahn 	printf("Block size=%u, Number of Blocks=%lu\n",
302dce63815Sdrahn 		zp->sbBlkSize, zp->sbBlkCount);
303dce63815Sdrahn 	printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%lx\n",
304dce63815Sdrahn 		zp->sbDevType, zp->sbDevId, zp->sbData);
305dce63815Sdrahn 	if (zp->sbDrvrCount == 0) {
306dce63815Sdrahn 	    printf("No drivers\n");
307dce63815Sdrahn 	} else {
308dce63815Sdrahn 	    printf("%u driver%s-\n", zp->sbDrvrCount,
309dce63815Sdrahn 		    (zp->sbDrvrCount>1)?"s":kStringEmpty);
31070060700Skrw 	    m = (struct ddmap *) zp->sbMap;
311dce63815Sdrahn 	    for (i = 0; i < zp->sbDrvrCount; i++) {
312dce63815Sdrahn             printf("%u: @ %lu for %u, type=0x%x\n", i+1,
313dce63815Sdrahn 		   get_align_long(&m[i].ddBlock),
314dce63815Sdrahn 		   m[i].ddSize, m[i].ddType);
315dce63815Sdrahn 	    }
316dce63815Sdrahn 	}
317dce63815Sdrahn     }
318dce63815Sdrahn     printf("\n");
319dce63815Sdrahn     printf(" #:                 type  length   base    "
320dce63815Sdrahn 	    "flags        (logical)\n");
321dce63815Sdrahn     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
322dce63815Sdrahn 	p = entry->data;
323dce63815Sdrahn 	printf("%2ld: %20.32s ",
324dce63815Sdrahn 		entry->disk_address, p->dpme_type);
325dce63815Sdrahn 	printf("%7lu @ %-7lu ", p->dpme_pblocks, p->dpme_pblock_start);
326dce63815Sdrahn 	printf("%c%c%c%c%c%c%c%c%c%c%c%c ",
327a1ac9a96Skrw 		(p->dpme_flags & DPME_VALID)?'V':'.',
328a1ac9a96Skrw 		(p->dpme_flags & DPME_ALLOCATED)?'A':'.',
329a1ac9a96Skrw 		(p->dpme_flags & DPME_IN_USE)?'I':'.',
330a1ac9a96Skrw 		(p->dpme_flags & DPME_BOOTABLE)?'B':'.',
331a1ac9a96Skrw 		(p->dpme_flags & DPME_READABLE)?'R':'.',
332a1ac9a96Skrw 		(p->dpme_flags & DPME_WRITABLE)?'W':'.',
333a1ac9a96Skrw 		(p->dpme_flags & DPME_OS_PIC_CODE)?'P':'.',
334a1ac9a96Skrw 		(p->dpme_flags & DPME_OS_SPECIFIC_2)?'2':'.',
335a1ac9a96Skrw 		(p->dpme_flags & DPME_CHAINABLE)?'C':'.',
336a1ac9a96Skrw 		(p->dpme_flags & DPME_DISKDRIVER)?'D':'.',
337a1ac9a96Skrw 		(p->dpme_flags & (1<<30))?'M':'.',
338a1ac9a96Skrw 		(p->dpme_flags & (1<<31))?'X':'.');
339dce63815Sdrahn 	if (p->dpme_lblock_start != 0 || p->dpme_pblocks != p->dpme_lblocks) {
340dce63815Sdrahn 	    printf("(%lu @ %lu)", p->dpme_lblocks, p->dpme_lblock_start);
341dce63815Sdrahn 	}
342dce63815Sdrahn 	printf("\n");
343dce63815Sdrahn     }
344dce63815Sdrahn     printf("\n");
345dce63815Sdrahn     printf(" #:  booter   bytes      load_address      "
346dce63815Sdrahn 	    "goto_address checksum processor\n");
347dce63815Sdrahn     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
348dce63815Sdrahn 	p = entry->data;
349dce63815Sdrahn 	printf("%2ld: ", entry->disk_address);
350dce63815Sdrahn 	printf("%7lu ", p->dpme_boot_block);
351dce63815Sdrahn 	printf("%7lu ", p->dpme_boot_bytes);
352dce63815Sdrahn 	printf("%8lx ", (u32)p->dpme_load_addr);
353dce63815Sdrahn 	printf("%8lx ", (u32)p->dpme_load_addr_2);
354dce63815Sdrahn 	printf("%8lx ", (u32)p->dpme_goto_addr);
355dce63815Sdrahn 	printf("%8lx ", (u32)p->dpme_goto_addr_2);
356dce63815Sdrahn 	printf("%8lx ", p->dpme_checksum);
357dce63815Sdrahn 	printf("%.32s", p->dpme_process_id);
358dce63815Sdrahn 	printf("\n");
359dce63815Sdrahn     }
360dce63815Sdrahn     printf("\n");
361dce63815Sdrahn }
362dce63815Sdrahn 
363dce63815Sdrahn 
364dce63815Sdrahn void
365b42d9302Smartin full_dump_partition_entry(partition_map_header *map, int ix)
366dce63815Sdrahn {
367dce63815Sdrahn     partition_map * cur;
3686521004eSkrw     struct dpme *p;
369dce63815Sdrahn     int i;
370dce63815Sdrahn     u32 t;
371dce63815Sdrahn 
372b42d9302Smartin     cur = find_entry_by_disk_address(ix, map);
373dce63815Sdrahn     if (cur == NULL) {
374dce63815Sdrahn 	printf("No such partition\n");
375dce63815Sdrahn 	return;
376dce63815Sdrahn     }
377dce63815Sdrahn 
378dce63815Sdrahn     p = cur->data;
379dce63815Sdrahn     printf("             signature: 0x%x\n", p->dpme_signature);
380dce63815Sdrahn     printf("             reserved1: 0x%x\n", p->dpme_reserved_1);
381dce63815Sdrahn     printf(" number of map entries: %ld\n", p->dpme_map_entries);
382dce63815Sdrahn     printf("        physical start: %10lu  length: %10lu\n", p->dpme_pblock_start, p->dpme_pblocks);
383dce63815Sdrahn     printf("         logical start: %10lu  length: %10lu\n", p->dpme_lblock_start, p->dpme_lblocks);
384dce63815Sdrahn 
385dce63815Sdrahn     printf("                 flags: 0x%lx\n", (u32)p->dpme_flags);
386dce63815Sdrahn     printf("                        ");
387a1ac9a96Skrw     if (p->dpme_flags & DPME_VALID) printf("valid ");
388a1ac9a96Skrw     if (p->dpme_flags & DPME_ALLOCATED) printf("alloc ");
389a1ac9a96Skrw     if (p->dpme_flags & DPME_IN_USE) printf("in-use ");
390a1ac9a96Skrw     if (p->dpme_flags & DPME_BOOTABLE) printf("boot ");
391a1ac9a96Skrw     if (p->dpme_flags & DPME_READABLE) printf("read ");
392a1ac9a96Skrw     if (p->dpme_flags & DPME_WRITABLE) printf("write ");
393a1ac9a96Skrw     if (p->dpme_flags & DPME_OS_PIC_CODE) printf("pic ");
394dce63815Sdrahn     t = p->dpme_flags >> 7;
395dce63815Sdrahn     for (i = 7; i <= 31; i++) {
396dce63815Sdrahn     	if (t & 0x1) {
397dce63815Sdrahn     	    printf("%d ", i);
398dce63815Sdrahn     	}
399dce63815Sdrahn     	t = t >> 1;
400dce63815Sdrahn     }
401dce63815Sdrahn     printf("\n");
402dce63815Sdrahn 
403dce63815Sdrahn     printf("                  name: '%.32s'\n", p->dpme_name);
404dce63815Sdrahn     printf("                  type: '%.32s'\n", p->dpme_type);
405dce63815Sdrahn 
406dce63815Sdrahn     printf("      boot start block: %10lu\n", p->dpme_boot_block);
407dce63815Sdrahn     printf("boot length (in bytes): %10lu\n", p->dpme_boot_bytes);
408dce63815Sdrahn     printf("          load address: 0x%08lx  0x%08lx\n",
409dce63815Sdrahn 		(u32)p->dpme_load_addr, (u32)p->dpme_load_addr_2);
410dce63815Sdrahn     printf("         start address: 0x%08lx  0x%08lx\n",
411dce63815Sdrahn 		(u32)p->dpme_goto_addr, (u32)p->dpme_goto_addr_2);
412dce63815Sdrahn     printf("              checksum: 0x%08lx\n", p->dpme_checksum);
413dce63815Sdrahn     printf("             processor: '%.32s'\n", p->dpme_process_id);
414dce63815Sdrahn     printf("boot args field -");
415dce63815Sdrahn     dump_block((unsigned char *)p->dpme_boot_args, 32*4);
416dce63815Sdrahn     printf("dpme_reserved_3 -");
417dce63815Sdrahn     dump_block((unsigned char *)p->dpme_reserved_3, 62*4);
418dce63815Sdrahn }
419dce63815Sdrahn 
420dce63815Sdrahn 
421dce63815Sdrahn void
422dce63815Sdrahn dump_block(unsigned char *addr, int len)
423dce63815Sdrahn {
424dce63815Sdrahn     int i;
425dce63815Sdrahn     int j;
426dce63815Sdrahn     int limit1;
427dce63815Sdrahn     int limit;
428dce63815Sdrahn #define LINE_LEN 16
429dce63815Sdrahn #define UNIT_LEN  4
430dce63815Sdrahn #define OTHER_LEN  8
431dce63815Sdrahn 
432dce63815Sdrahn     for (i = 0; i < len; i = limit) {
433dce63815Sdrahn     	limit1 = i + LINE_LEN;
434dce63815Sdrahn     	if (limit1 > len) {
435dce63815Sdrahn     	    limit = len;
436dce63815Sdrahn     	} else {
437dce63815Sdrahn     	    limit = limit1;
438dce63815Sdrahn     	}
439dce63815Sdrahn 	printf("\n%03x: ", i);
440dce63815Sdrahn     	for (j = i; j < limit1; j++) {
441dce63815Sdrahn 	    if (j % UNIT_LEN == 0) {
442dce63815Sdrahn 		printf(" ");
443dce63815Sdrahn 	    }
444dce63815Sdrahn 	    if (j < limit) {
445dce63815Sdrahn 		printf("%02x", addr[j]);
446dce63815Sdrahn 	    } else {
447dce63815Sdrahn 		printf("  ");
448dce63815Sdrahn 	    }
449dce63815Sdrahn     	}
450dce63815Sdrahn 	printf(" ");
451dce63815Sdrahn     	for (j = i; j < limit; j++) {
452dce63815Sdrahn 	    if (j % OTHER_LEN == 0) {
453dce63815Sdrahn 		printf(" ");
454dce63815Sdrahn 	    }
455dce63815Sdrahn     	    if (addr[j] < ' ') {
456dce63815Sdrahn     	    	printf(".");
457dce63815Sdrahn     	    } else {
458dce63815Sdrahn     	    	printf("%c", addr[j]);
459dce63815Sdrahn     	    }
460dce63815Sdrahn     	}
461dce63815Sdrahn     }
462dce63815Sdrahn     printf("\n");
463dce63815Sdrahn }
464dce63815Sdrahn 
465dce63815Sdrahn void
466dce63815Sdrahn full_dump_block_zero(partition_map_header *map)
467dce63815Sdrahn {
46871bd5f9cSkrw     struct block0 *zp;
46970060700Skrw     struct ddmap *m;
470dce63815Sdrahn     int i;
471dce63815Sdrahn 
472dce63815Sdrahn     if (map == NULL) {
473dce63815Sdrahn 	printf("No partition map exists\n");
474dce63815Sdrahn 	return;
475dce63815Sdrahn     }
476dce63815Sdrahn 
477dce63815Sdrahn     if (map->misc == NULL) {
478dce63815Sdrahn 	printf("No block zero\n");
479dce63815Sdrahn 	return;
480dce63815Sdrahn     }
481dce63815Sdrahn     zp = map->misc;
482dce63815Sdrahn 
483dce63815Sdrahn     printf("             signature: 0x%x\n", zp->sbSig);
484dce63815Sdrahn     printf("       size of a block: %d\n", zp->sbBlkSize);
485dce63815Sdrahn     printf("      number of blocks: %ld\n", zp->sbBlkCount);
486dce63815Sdrahn     printf("           device type: 0x%x\n", zp->sbDevType);
487dce63815Sdrahn     printf("             device id: 0x%x\n", zp->sbDevId);
488dce63815Sdrahn     printf("                  data: 0x%lx\n", zp->sbData);
489dce63815Sdrahn     printf("          driver count: %d\n", zp->sbDrvrCount);
49070060700Skrw     m = (struct ddmap *) zp->sbMap;
491dce63815Sdrahn     for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) {
492dce63815Sdrahn     	if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) {
493dce63815Sdrahn     	    break;
494dce63815Sdrahn     	}
495dce63815Sdrahn 	printf("      driver %3u block: %ld\n", i+1, m[i].ddBlock);
496dce63815Sdrahn 	printf("        size in blocks: %d\n", m[i].ddSize);
497dce63815Sdrahn 	printf("           driver type: 0x%x\n", m[i].ddType);
498dce63815Sdrahn     }
499dce63815Sdrahn     printf("remainder of block -");
500dce63815Sdrahn     dump_block((unsigned char *)&m[i].ddBlock, (&zp->sbMap[247]-((unsigned short *)&m[i].ddBlock))*2);
501dce63815Sdrahn }
502dce63815Sdrahn 
503b42d9302Smartin 
504dce63815Sdrahn void
505dce63815Sdrahn display_patches(partition_map *entry)
506dce63815Sdrahn {
507dce63815Sdrahn     long long offset;
5086a69102aSkrw     struct file_media *m;
509dce63815Sdrahn     static unsigned char *patch_block;
510*94d20309Skrw     struct patchlist *p;
511*94d20309Skrw     struct patchdescriptor *q;
512b42d9302Smartin     unsigned char *next;
513b42d9302Smartin     unsigned char *s;
514b42d9302Smartin     int i;
515dce63815Sdrahn 
516dce63815Sdrahn     offset = entry->data->dpme_pblock_start;
517dce63815Sdrahn     m = entry->the_map->m;
518dce63815Sdrahn     offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block;
519dce63815Sdrahn     if (patch_block == NULL) {
520d66063cbSkrw 	patch_block = malloc(DEV_BSIZE);
521dce63815Sdrahn 	if (patch_block == NULL) {
52268d0f91bSkrw 	    warn("can't allocate memory for patch block buffer");
523dce63815Sdrahn 	    return;
524dce63815Sdrahn 	}
525dce63815Sdrahn     }
526f42746d7Skrw     if (read_file_media(m, (long long)offset, DEV_BSIZE, (char *)patch_block) == 0) {
52768d0f91bSkrw 	warn("Can't read patch block");
528dce63815Sdrahn 	return;
529dce63815Sdrahn     }
530*94d20309Skrw     p = (struct patchlist *) patch_block;
531b42d9302Smartin     if (p->numPatchBlocks != 1) {
532b42d9302Smartin 	i = p->numPatchBlocks;
533b42d9302Smartin 	free(patch_block);
534d66063cbSkrw 	patch_block = reallocarray(NULL, i, DEV_BSIZE);
535b42d9302Smartin 	if (patch_block == NULL) {
53668d0f91bSkrw 	    warn("can't allocate memory for patch blocks buffer");
537b42d9302Smartin 	    return;
538b42d9302Smartin 	}
539d66063cbSkrw 	s = patch_block + DEV_BSIZE*i;
540b42d9302Smartin 	while (i > 0) {
541d66063cbSkrw 	    s -= DEV_BSIZE;
542b42d9302Smartin 	    i -= 1;
543f42746d7Skrw 	    if (read_file_media(m, offset+i, DEV_BSIZE, (char *)s) == 0) {
54468d0f91bSkrw 		warn("Can't read patch block %d", i);
545b42d9302Smartin 		return;
546b42d9302Smartin 	    }
547b42d9302Smartin 	}
548*94d20309Skrw 	p = (struct patchlist *) patch_block;
549b42d9302Smartin     }
550b42d9302Smartin     printf("Patch list (%d entries)\n", p->numPatches);
551b42d9302Smartin     q = p->thePatch;
552b42d9302Smartin     for (i = 0; i < p->numPatches; i++) {
553b42d9302Smartin 	printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig);
554b42d9302Smartin 	printf("     version: %d.%d\n", q->majorVers, q->minorVers);
555b42d9302Smartin 	printf("       flags: 0x%lx\n", q->flags);
556b42d9302Smartin 	printf("      offset: %ld\n", q->patchOffset);
557b42d9302Smartin 	printf("        size: %ld\n", q->patchSize);
558b42d9302Smartin 	printf("         CRC: 0x%lx\n", q->patchCRC);
559b42d9302Smartin 	printf("        name: '%.*s'\n", q->patchName[0], &q->patchName[1]);
560b42d9302Smartin 	printf("      vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]);
561b42d9302Smartin 	next = ((unsigned char *)q) + q->patchDescriptorLen;
562b42d9302Smartin 	s = &q->patchVendor[q->patchVendor[0]+1];
563b42d9302Smartin 	if (next > s) {
564b42d9302Smartin 	    printf("remainder of entry -");
565b42d9302Smartin 	    dump_block(s, next-s);
566b42d9302Smartin 	}
567*94d20309Skrw 	q = (struct patchdescriptor *)next;
568b42d9302Smartin     }
569dce63815Sdrahn }
570dce63815Sdrahn 
571dce63815Sdrahn int
572dce63815Sdrahn get_max_type_string_length(partition_map_header *map)
573dce63815Sdrahn {
574dce63815Sdrahn     partition_map * entry;
575dce63815Sdrahn     int max;
576dce63815Sdrahn     int length;
577dce63815Sdrahn 
578dce63815Sdrahn     if (map == NULL) {
579dce63815Sdrahn 	return 0;
580dce63815Sdrahn     }
581dce63815Sdrahn 
582dce63815Sdrahn     max = 0;
583dce63815Sdrahn 
584dce63815Sdrahn     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
585dce63815Sdrahn 	length = strnlen(entry->data->dpme_type, DPISTRLEN);
586dce63815Sdrahn 	if (length > max) {
587dce63815Sdrahn 	    max = length;
588dce63815Sdrahn 	}
589dce63815Sdrahn     }
590dce63815Sdrahn 
591dce63815Sdrahn     return max;
592dce63815Sdrahn }
593dce63815Sdrahn 
594dce63815Sdrahn int
595dce63815Sdrahn get_max_name_string_length(partition_map_header *map)
596dce63815Sdrahn {
597dce63815Sdrahn     partition_map * entry;
598dce63815Sdrahn     int max;
599dce63815Sdrahn     int length;
600dce63815Sdrahn 
601dce63815Sdrahn     if (map == NULL) {
602dce63815Sdrahn 	return 0;
603dce63815Sdrahn     }
604dce63815Sdrahn 
605dce63815Sdrahn     max = 0;
606dce63815Sdrahn 
607dce63815Sdrahn     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
608dce63815Sdrahn 	length = strnlen(entry->data->dpme_name, DPISTRLEN);
609dce63815Sdrahn 	if (length > max) {
610dce63815Sdrahn 	    max = length;
611dce63815Sdrahn 	}
612dce63815Sdrahn     }
613dce63815Sdrahn 
614dce63815Sdrahn     return max;
615dce63815Sdrahn }
616dce63815Sdrahn 
617dce63815Sdrahn int
618dce63815Sdrahn get_max_base_or_length(partition_map_header *map)
619dce63815Sdrahn {
620dce63815Sdrahn     partition_map * entry;
621dce63815Sdrahn     int max;
622dce63815Sdrahn 
623dce63815Sdrahn     if (map == NULL) {
624dce63815Sdrahn 	return 0;
625dce63815Sdrahn     }
626dce63815Sdrahn 
627dce63815Sdrahn     max = 0;
628dce63815Sdrahn 
629dce63815Sdrahn     for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
630dce63815Sdrahn 	if (entry->data->dpme_pblock_start > max) {
631dce63815Sdrahn 	    max = entry->data->dpme_pblock_start;
632dce63815Sdrahn 	}
633dce63815Sdrahn 	if (entry->data->dpme_pblocks > max) {
634dce63815Sdrahn 	    max = entry->data->dpme_pblocks;
635dce63815Sdrahn 	}
636dce63815Sdrahn 	if (entry->data->dpme_lblock_start > max) {
637dce63815Sdrahn 	    max = entry->data->dpme_lblock_start;
638dce63815Sdrahn 	}
639dce63815Sdrahn 	if (entry->data->dpme_lblocks > max) {
640dce63815Sdrahn 	    max = entry->data->dpme_lblocks;
641dce63815Sdrahn 	}
642dce63815Sdrahn     }
643dce63815Sdrahn 
644dce63815Sdrahn     return max;
645dce63815Sdrahn }
646dce63815Sdrahn 
647dce63815Sdrahn void
648dce63815Sdrahn adjust_value_and_compute_prefix(double *value, int *prefix)
649dce63815Sdrahn {
650dce63815Sdrahn     double bytes;
651dce63815Sdrahn     int multiplier;
652dce63815Sdrahn 
653dce63815Sdrahn     bytes = *value;
654dce63815Sdrahn     if (bytes < 1024.0) {
655dce63815Sdrahn 	multiplier = ' ';
656dce63815Sdrahn     } else {
657dce63815Sdrahn 	bytes = bytes / 1024.0;
658dce63815Sdrahn 	if (bytes < 1024.0) {
659dce63815Sdrahn 	    multiplier = 'K';
660dce63815Sdrahn 	} else {
661dce63815Sdrahn 	    bytes = bytes / 1024.0;
662dce63815Sdrahn 	    if (bytes < 1024.0) {
663dce63815Sdrahn 		multiplier = 'M';
664dce63815Sdrahn 	    } else {
665dce63815Sdrahn 		bytes = bytes / 1024.0;
666dce63815Sdrahn 		if (bytes < 1024.0) {
667dce63815Sdrahn 		    multiplier = 'G';
668dce63815Sdrahn 		} else {
669dce63815Sdrahn 		    bytes = bytes / 1024.0;
670dce63815Sdrahn 		    multiplier = 'T';
671dce63815Sdrahn 		}
672dce63815Sdrahn 	    }
673dce63815Sdrahn 	}
674dce63815Sdrahn     }
675dce63815Sdrahn     *value = bytes;
676dce63815Sdrahn     *prefix = multiplier;
677dce63815Sdrahn }
678