1/*	$OpenBSD: dump.c,v 1.75 2016/02/23 02:39:54 krw Exp $	*/
2
3/*
4 * dump.c - dumping partition maps
5 *
6 * Written by Eryk Vershen
7 */
8
9/*
10 * Copyright 1996,1997,1998 by Apple Computer, Inc.
11 *              All Rights Reserved
12 *
13 * Permission to use, copy, modify, and distribute this software and
14 * its documentation for any purpose and without fee is hereby granted,
15 * provided that the above copyright notice appears in all copies and
16 * that both the copyright notice and this permission notice appear in
17 * supporting documentation.
18 *
19 * APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
20 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE.
22 *
23 * IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
24 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
26 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
27 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 */
29
30#include <sys/queue.h>
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <util.h>
36
37#include "partition_map.h"
38#include "dump.h"
39#include "io.h"
40
41void	dump_block(unsigned char *, int);
42void	dump_block_zero(struct partition_map *);
43void	dump_partition_entry(struct entry *, int, int, int);
44int	get_max_base_or_length(struct partition_map *);
45int	get_max_name_string_length(struct partition_map *);
46int	get_max_type_string_length(struct partition_map *);
47
48void
49dump_block_zero(struct partition_map *map)
50{
51	char buf[FMT_SCALED_STRSIZE];
52	struct ddmap  *m;
53	int i;
54
55	printf("\nDevice block size=%u, Number of Blocks=%u",
56	       map->sbBlkSize, map->sbBlkCount);
57	if (fmt_scaled((long long)map->sbBlkCount * map->sbBlkSize, buf) == 0)
58		printf(" (%s)\n", buf);
59	else
60		printf("\n");
61
62	printf("DeviceType=0x%x, DeviceId=0x%x\n", map->sbDevType,
63	    map->sbDevId);
64	if (map->sbDrvrCount > 0) {
65		printf("Drivers-\n");
66		m = map->sbDDMap;
67		for (i = 0; i < map->sbDrvrCount; i++) {
68			printf("%d: %3u @ %u, ", i + 1, m[i].ddSize,
69			    m[i].ddBlock);
70			printf("type=0x%x\n", m[i].ddType);
71		}
72	}
73	printf("\n");
74}
75
76
77void
78dump_partition_map(struct partition_map *map)
79{
80	struct entry *entry;
81	int digits, max_type_length, max_name_length;
82
83	printf("\nPartition map (with %d byte blocks) on '%s'\n",
84	       map->sbBlkSize, map->name);
85
86	digits = number_of_digits(get_max_base_or_length(map));
87	if (digits < 6)
88		digits = 6;
89	max_type_length = get_max_type_string_length(map);
90	if (max_type_length < 4)
91		max_type_length = 4;
92	max_name_length = get_max_name_string_length(map);
93	if (max_name_length < 6)
94		max_name_length = 6;
95	printf(" #: %*s %-*s %*s   %-*s\n", max_type_length, "type",
96	    max_name_length, "name", digits, "length", digits, "base");
97
98	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
99		dump_partition_entry(entry, max_type_length,
100		    max_name_length, digits);
101	}
102	dump_block_zero(map);
103}
104
105
106void
107dump_partition_entry(struct entry *entry, int type_length, int name_length,
108    int digits)
109{
110	char buf[FMT_SCALED_STRSIZE];
111
112	printf("%2ld: %*.32s", entry->disk_address, type_length,
113	    entry->dpme_type);
114	printf("%c%-*.32s ", contains_driver(entry) ? '*' : ' ',
115	    name_length, entry->dpme_name);
116
117	printf("%*u @ %-*u", digits, entry->dpme_pblocks, digits,
118	    entry->dpme_pblock_start);
119
120	if (fmt_scaled((long long)entry->dpme_pblocks *
121	    entry->the_map->sbBlkSize, buf) == 0)
122		printf("(%s)\n", buf);
123	else
124		printf("\n");
125}
126
127
128void
129show_data_structures(struct partition_map *map)
130{
131	struct entry *entry;
132	struct ddmap *m;
133	int i;
134
135	printf("Header:\n");
136	printf("map %d blocks out of %d,  media %lu blocks (%d byte blocks)\n",
137	    map->blocks_in_map, map->maximum_in_map, map->media_size,
138	    map->sbBlkSize);
139	printf("Map is%s writable", rflag ? " not" : "");
140	printf(" and has%s been changed\n", (map->changed) ? "" : " not");
141	printf("\n");
142
143	printf("Block0:\n");
144	printf("signature 0x%x", map->sbSig);
145	printf("Block size=%u, Number of Blocks=%u\n", map->sbBlkSize,
146	    map->sbBlkCount);
147	printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%x\n", map->sbDevType,
148	    map->sbDevId, map->sbData);
149	if (map->sbDrvrCount == 0) {
150		printf("No drivers\n");
151	} else {
152		printf("%u driver%s-\n", map->sbDrvrCount,
153		    (map->sbDrvrCount > 1) ? "s" : "");
154		m = map->sbDDMap;
155		for (i = 0; i < map->sbDrvrCount; i++) {
156			printf("%u: @ %u for %u, type=0x%x\n", i + 1,
157			    m[i].ddBlock, m[i].ddSize, m[i].ddType);
158		}
159	}
160	printf("\n");
161	printf(" #:                 type  length   base    "
162	       "flags     (      logical      )\n");
163	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
164		printf("%2ld: %20.32s ", entry->disk_address, entry->dpme_type);
165		printf("%7u @ %-7u ", entry->dpme_pblocks,
166		    entry->dpme_pblock_start);
167		printf("%c%c%c%c%c%c%c%c%c ",
168		       (entry->dpme_flags & DPME_VALID) ? 'V' : '.',
169		       (entry->dpme_flags & DPME_ALLOCATED) ? 'A' : '.',
170		       (entry->dpme_flags & DPME_IN_USE) ? 'I' : '.',
171		       (entry->dpme_flags & DPME_BOOTABLE) ? 'B' : '.',
172		       (entry->dpme_flags & DPME_READABLE) ? 'R' : '.',
173		       (entry->dpme_flags & DPME_WRITABLE) ? 'W' : '.',
174		       (entry->dpme_flags & DPME_OS_PIC_CODE) ? 'P' : '.',
175		       (entry->dpme_flags & DPME_OS_SPECIFIC_2) ? '2' : '.',
176		       (entry->dpme_flags & DPME_OS_SPECIFIC_1) ? '1' : '.');
177		printf("( %7u @ %-7u )\n", entry->dpme_lblocks,
178		    entry->dpme_lblock_start);
179	}
180	printf("\n");
181	printf(" #:  booter   bytes      load_address      "
182	    "goto_address checksum processor\n");
183	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
184		printf("%2ld: ", entry->disk_address);
185		printf("%7u ", entry->dpme_boot_block);
186		printf("%7u ", entry->dpme_boot_bytes);
187		printf("%8x ", entry->dpme_load_addr);
188		printf("%8x ", entry->dpme_goto_addr);
189		printf("%8x ", entry->dpme_checksum);
190		printf("%.32s", entry->dpme_processor_id);
191		printf("\n");
192	}
193	printf("\n");
194}
195
196
197void
198full_dump_partition_entry(struct partition_map *map, int ix)
199{
200	struct entry *entry;
201	int i;
202	uint32_t t;
203
204	entry = find_entry_by_disk_address(ix, map);
205	if (entry == NULL) {
206		printf("No such partition\n");
207		return;
208	}
209	printf("             signature: 0x%x\n", entry->dpme_signature);
210	printf(" number of map entries: %u\n", entry->dpme_map_entries);
211	printf("        physical start: %10u  length: %10u\n",
212	    entry->dpme_pblock_start, entry->dpme_pblocks);
213	printf("         logical start: %10u  length: %10u\n",
214	    entry->dpme_lblock_start, entry->dpme_lblocks);
215
216	printf("                 flags: 0x%x\n", entry->dpme_flags);
217	printf("                        ");
218	if (entry->dpme_flags & DPME_VALID)
219		printf("valid ");
220	if (entry->dpme_flags & DPME_ALLOCATED)
221		printf("alloc ");
222	if (entry->dpme_flags & DPME_IN_USE)
223		printf("in-use ");
224	if (entry->dpme_flags & DPME_BOOTABLE)
225		printf("boot ");
226	if (entry->dpme_flags & DPME_READABLE)
227		printf("read ");
228	if (entry->dpme_flags & DPME_WRITABLE)
229		printf("write ");
230	if (entry->dpme_flags & DPME_OS_PIC_CODE)
231		printf("pic ");
232	t = entry->dpme_flags >> 7;
233	for (i = 7; i <= 31; i++) {
234		if (t & 0x1)
235			printf("%d ", i);
236		t = t >> 1;
237	}
238	printf("\n");
239
240	printf("                  name: '%.32s'\n", entry->dpme_name);
241	printf("                  type: '%.32s'\n", entry->dpme_type);
242	printf("      boot start block: %10u\n", entry->dpme_boot_block);
243	printf("boot length (in bytes): %10u\n", entry->dpme_boot_bytes);
244	printf("          load address: 0x%08x\n", entry->dpme_load_addr);
245	printf("         start address: 0x%08x\n", entry->dpme_goto_addr);
246	printf("              checksum: 0x%08x\n", entry->dpme_checksum);
247	printf("             processor: '%.32s'\n", entry->dpme_processor_id);
248	printf("dpme_reserved_1 -");
249	dump_block(entry->dpme_reserved_1, sizeof(entry->dpme_reserved_1));
250	printf("dpme_reserved_2 -");
251	dump_block(entry->dpme_reserved_2, sizeof(entry->dpme_reserved_2));
252	printf("dpme_reserved_3 -");
253	dump_block(entry->dpme_reserved_3, sizeof(entry->dpme_reserved_3));
254	printf("dpme_reserved_4 -");
255	dump_block(entry->dpme_reserved_4, sizeof(entry->dpme_reserved_4));
256}
257
258
259void
260dump_block(unsigned char *addr, int len)
261{
262	int i, j, limit1, limit;
263
264#define LINE_LEN 16
265#define UNIT_LEN  4
266#define OTHER_LEN  8
267
268	for (i = 0; i < len; i = limit) {
269		limit1 = i + LINE_LEN;
270		if (limit1 > len)
271			limit = len;
272		else
273			limit = limit1;
274		printf("\n%03x: ", i);
275		for (j = i; j < limit1; j++) {
276			if (j % UNIT_LEN == 0)
277				printf(" ");
278			if (j < limit)
279				printf("%02x", addr[j]);
280			else
281				printf("  ");
282		}
283		printf(" ");
284		for (j = i; j < limit; j++) {
285			if (j % OTHER_LEN == 0)
286				printf(" ");
287			if (addr[j] < ' ')
288				printf(".");
289			else
290				printf("%c", addr[j]);
291		}
292	}
293	printf("\n");
294}
295
296void
297full_dump_block_zero(struct partition_map *map)
298{
299	struct ddmap *m;
300	int i;
301
302	m = map->sbDDMap;
303
304	printf("             signature: 0x%x\n", map->sbSig);
305	printf("       size of a block: %u\n", map->sbBlkSize);
306	printf("      number of blocks: %u\n", map->sbBlkCount);
307	printf("           device type: 0x%x\n", map->sbDevType);
308	printf("             device id: 0x%x\n", map->sbDevId);
309	printf("                  data: 0x%x\n", map->sbData);
310	printf("          driver count: %u\n", map->sbDrvrCount);
311	for (i = 0; i < 8; i++) {
312		if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0)
313			break;
314		printf("      driver %3u block: %u\n", i + 1, m[i].ddBlock);
315		printf("        size in blocks: %u\n", m[i].ddSize);
316		printf("           driver type: 0x%x\n", m[i].ddType);
317	}
318	printf("remainder of block -");
319	dump_block(map->sbReserved, sizeof(map->sbReserved));
320}
321
322int
323get_max_type_string_length(struct partition_map *map)
324{
325	struct entry *entry;
326	int max, length;
327
328	max = 0;
329
330	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
331		length = strnlen(entry->dpme_type, DPISTRLEN);
332		if (length > max)
333			max = length;
334	}
335
336	return max;
337}
338
339int
340get_max_name_string_length(struct partition_map *map)
341{
342	struct entry *entry;
343	int max, length;
344
345	max = 0;
346
347	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
348		length = strnlen(entry->dpme_name, DPISTRLEN);
349		if (length > max)
350			max = length;
351	}
352
353	return max;
354}
355
356int
357get_max_base_or_length(struct partition_map *map)
358{
359	struct entry *entry;
360	int max;
361
362	max = 0;
363
364	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
365		if (entry->dpme_pblock_start > max)
366			max = entry->dpme_pblock_start;
367		if (entry->dpme_pblocks > max)
368			max = entry->dpme_pblocks;
369	}
370
371	return max;
372}
373