xref: /openbsd-src/sbin/pdisk/dump.c (revision 6f012227d275893711279b51a984b96439466227)
1 /*	$OpenBSD: dump.c,v 1.67 2016/01/29 22:51:43 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 
36 #include "dpme.h"
37 #include "partition_map.h"
38 #include "dump.h"
39 #include "io.h"
40 
41 void	adjust_value_and_compute_prefix(double *, int *);
42 void	dump_block_zero(struct partition_map *);
43 void	dump_partition_entry(struct entry *, int, int, int);
44 int	get_max_base_or_length(struct partition_map *);
45 int	get_max_name_string_length(struct partition_map *);
46 int	get_max_type_string_length(struct partition_map *);
47 
48 void
49 dump_block_zero(struct partition_map *map)
50 {
51 	struct ddmap  *m;
52 	double value;
53 	int i, prefix;
54 
55 	value = ((double)map->sbBlkCount) * map->sbBlkSize;
56 	adjust_value_and_compute_prefix(&value, &prefix);
57 	printf("\nDevice block size=%u, Number of Blocks=%u (%1.1f%c)\n",
58 	       map->sbBlkSize, map->sbBlkCount, value, prefix);
59 
60 	printf("DeviceType=0x%x, DeviceId=0x%x\n", map->sbDevType,
61 	    map->sbDevId);
62 	if (map->sbDrvrCount > 0) {
63 		printf("Drivers-\n");
64 		m = map->sbDDMap;
65 		for (i = 0; i < map->sbDrvrCount; i++) {
66 			printf("%d: %3u @ %u, ", i + 1, m[i].ddSize,
67 			    m[i].ddBlock);
68 			printf("type=0x%x\n", m[i].ddType);
69 		}
70 	}
71 	printf("\n");
72 }
73 
74 
75 void
76 dump_partition_map(struct partition_map *map)
77 {
78 	struct entry *entry;
79 	int digits, max_type_length, max_name_length;
80 
81 	printf("\nPartition map (with %d byte blocks) on '%s'\n",
82 	       map->physical_block, map->name);
83 
84 	digits = number_of_digits(get_max_base_or_length(map));
85 	if (digits < 6)
86 		digits = 6;
87 	max_type_length = get_max_type_string_length(map);
88 	if (max_type_length < 4)
89 		max_type_length = 4;
90 	max_name_length = get_max_name_string_length(map);
91 	if (max_name_length < 6)
92 		max_name_length = 6;
93 	printf(" #: %*s %-*s %*s   %-*s ( size )\n", max_type_length, "type",
94 	    max_name_length, "name", digits, "length", digits, "base");
95 
96 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
97 		dump_partition_entry(entry, max_type_length,
98 		    max_name_length, digits);
99 	}
100 	dump_block_zero(map);
101 }
102 
103 
104 void
105 dump_partition_entry(struct entry *entry, int type_length,
106     int name_length, int digits)
107 {
108 	struct partition_map *map;
109 	struct dpme *p;
110 	double bytes;
111 	int j, driver;
112 
113 	map = entry->the_map;
114 	p = entry->dpme;
115 	driver = entry->contains_driver ? '*' : ' ';
116 	printf("%2ld: %*.32s", entry->disk_address, type_length, p->dpme_type);
117 	printf("%c%-*.32s ", driver, name_length, p->dpme_name);
118 
119 	printf("%*u @ %-*u", digits, p->dpme_pblocks, digits,
120 	    p->dpme_pblock_start);
121 
122 	bytes = ((double) p->dpme_pblocks) * map->physical_block;
123 	adjust_value_and_compute_prefix(&bytes, &j);
124 	if (j != ' ' && j != 'K')
125 		printf(" (%#5.1f%c)", bytes, j);
126 	printf("\n");
127 }
128 
129 
130 void
131 show_data_structures(struct partition_map *map)
132 {
133 	struct entry *entry;
134 	struct ddmap *m;
135 	struct dpme *p;
136 	int i;
137 
138 	printf("Header:\n");
139 	printf("map %d blocks out of %d,  media %lu blocks (%d byte blocks)\n",
140 	    map->blocks_in_map, map->maximum_in_map, map->media_size,
141 	    map->physical_block);
142 	printf("Map is%s writable", rflag ? " not" : "");
143 	printf(" and has%s been changed\n", (map->changed) ? "" : " not");
144 	printf("\n");
145 
146 	printf("Block0:\n");
147 	printf("signature 0x%x", map->sbSig);
148 	printf("Block size=%u, Number of Blocks=%u\n", map->sbBlkSize,
149 	    map->sbBlkCount);
150 	printf("DeviceType=0x%x, DeviceId=0x%x, sbData=0x%x\n", map->sbDevType,
151 	    map->sbDevId, map->sbData);
152 	if (map->sbDrvrCount == 0) {
153 		printf("No drivers\n");
154 	} else {
155 		printf("%u driver%s-\n", map->sbDrvrCount,
156 		    (map->sbDrvrCount > 1) ? "s" : "");
157 		m = map->sbDDMap;
158 		for (i = 0; i < map->sbDrvrCount; i++) {
159 			printf("%u: @ %u for %u, type=0x%x\n", i + 1,
160 			    m[i].ddBlock, m[i].ddSize, m[i].ddType);
161 		}
162 	}
163 	printf("\n");
164 	printf(" #:                 type  length   base    "
165 	       "flags     (      logical      )\n");
166 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
167 		p = entry->dpme;
168 		printf("%2ld: %20.32s ", entry->disk_address, p->dpme_type);
169 		printf("%7u @ %-7u ", p->dpme_pblocks, p->dpme_pblock_start);
170 		printf("%c%c%c%c%c%c%c%c%c ",
171 		       (p->dpme_flags & DPME_VALID) ? 'V' : '.',
172 		       (p->dpme_flags & DPME_ALLOCATED) ? 'A' : '.',
173 		       (p->dpme_flags & DPME_IN_USE) ? 'I' : '.',
174 		       (p->dpme_flags & DPME_BOOTABLE) ? 'B' : '.',
175 		       (p->dpme_flags & DPME_READABLE) ? 'R' : '.',
176 		       (p->dpme_flags & DPME_WRITABLE) ? 'W' : '.',
177 		       (p->dpme_flags & DPME_OS_PIC_CODE) ? 'P' : '.',
178 		       (p->dpme_flags & DPME_OS_SPECIFIC_2) ? '2' : '.',
179 		       (p->dpme_flags & DPME_OS_SPECIFIC_1) ? '1' : '.');
180 		printf("( %7u @ %-7u )\n", p->dpme_lblocks,
181 		    p->dpme_lblock_start);
182 	}
183 	printf("\n");
184 	printf(" #:  booter   bytes      load_address      "
185 	    "goto_address checksum processor\n");
186 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
187 		p = entry->dpme;
188 		printf("%2ld: ", entry->disk_address);
189 		printf("%7u ", p->dpme_boot_block);
190 		printf("%7u ", p->dpme_boot_bytes);
191 		printf("%8x ", p->dpme_load_addr);
192 		printf("%8x ", p->dpme_goto_addr);
193 		printf("%8x ", p->dpme_checksum);
194 		printf("%.32s", p->dpme_processor_id);
195 		printf("\n");
196 	}
197 	printf("\n");
198 }
199 
200 
201 void
202 full_dump_partition_entry(struct partition_map *map, int ix)
203 {
204 	struct entry *cur;
205 	struct dpme *p;
206 	int i;
207 	uint32_t t;
208 
209 	cur = find_entry_by_disk_address(ix, map);
210 	if (cur == NULL) {
211 		printf("No such partition\n");
212 		return;
213 	}
214 	p = cur->dpme;
215 	printf("             signature: 0x%x\n", p->dpme_signature);
216 	printf(" number of map entries: %u\n", p->dpme_map_entries);
217 	printf("        physical start: %10u  length: %10u\n",
218 	    p->dpme_pblock_start, p->dpme_pblocks);
219 	printf("         logical start: %10u  length: %10u\n",
220 	    p->dpme_lblock_start, p->dpme_lblocks);
221 
222 	printf("                 flags: 0x%x\n", (uint32_t)p->dpme_flags);
223 	printf("                        ");
224 	if (p->dpme_flags & DPME_VALID)
225 		printf("valid ");
226 	if (p->dpme_flags & DPME_ALLOCATED)
227 		printf("alloc ");
228 	if (p->dpme_flags & DPME_IN_USE)
229 		printf("in-use ");
230 	if (p->dpme_flags & DPME_BOOTABLE)
231 		printf("boot ");
232 	if (p->dpme_flags & DPME_READABLE)
233 		printf("read ");
234 	if (p->dpme_flags & DPME_WRITABLE)
235 		printf("write ");
236 	if (p->dpme_flags & DPME_OS_PIC_CODE)
237 		printf("pic ");
238 	t = p->dpme_flags >> 7;
239 	for (i = 7; i <= 31; i++) {
240 		if (t & 0x1)
241 			printf("%d ", i);
242 		t = t >> 1;
243 	}
244 	printf("\n");
245 
246 	printf("                  name: '%.32s'\n", p->dpme_name);
247 	printf("                  type: '%.32s'\n", p->dpme_type);
248 	printf("      boot start block: %10u\n", p->dpme_boot_block);
249 	printf("boot length (in bytes): %10u\n", p->dpme_boot_bytes);
250 	printf("          load address: 0x%08x\n", p->dpme_load_addr);
251 	printf("         start address: 0x%08x\n", p->dpme_goto_addr);
252 	printf("              checksum: 0x%08x\n", p->dpme_checksum);
253 	printf("             processor: '%.32s'\n", p->dpme_processor_id);
254 	printf("dpme_reserved_1 -");
255 	dump_block(p->dpme_reserved_1, sizeof(p->dpme_reserved_1));
256 	printf("dpme_reserved_2 -");
257 	dump_block(p->dpme_reserved_2, sizeof(p->dpme_reserved_2));
258 	printf("dpme_reserved_3 -");
259 	dump_block(p->dpme_reserved_3, sizeof(p->dpme_reserved_3));
260 	printf("dpme_reserved_4 -");
261 	dump_block(p->dpme_reserved_4, sizeof(p->dpme_reserved_4));
262 }
263 
264 
265 void
266 dump_block(unsigned char *addr, int len)
267 {
268 	int i, j, limit1, limit;
269 
270 #define LINE_LEN 16
271 #define UNIT_LEN  4
272 #define OTHER_LEN  8
273 
274 	for (i = 0; i < len; i = limit) {
275 		limit1 = i + LINE_LEN;
276 		if (limit1 > len)
277 			limit = len;
278 		else
279 			limit = limit1;
280 		printf("\n%03x: ", i);
281 		for (j = i; j < limit1; j++) {
282 			if (j % UNIT_LEN == 0)
283 				printf(" ");
284 			if (j < limit)
285 				printf("%02x", addr[j]);
286 			else
287 				printf("  ");
288 		}
289 		printf(" ");
290 		for (j = i; j < limit; j++) {
291 			if (j % OTHER_LEN == 0)
292 				printf(" ");
293 			if (addr[j] < ' ')
294 				printf(".");
295 			else
296 				printf("%c", addr[j]);
297 		}
298 	}
299 	printf("\n");
300 }
301 
302 void
303 full_dump_block_zero(struct partition_map *map)
304 {
305 	struct ddmap *m;
306 	int i;
307 
308 	m = map->sbDDMap;
309 
310 	printf("             signature: 0x%x\n", map->sbSig);
311 	printf("       size of a block: %u\n", map->sbBlkSize);
312 	printf("      number of blocks: %u\n", map->sbBlkCount);
313 	printf("           device type: 0x%x\n", map->sbDevType);
314 	printf("             device id: 0x%x\n", map->sbDevId);
315 	printf("                  data: 0x%x\n", map->sbData);
316 	printf("          driver count: %u\n", map->sbDrvrCount);
317 	for (i = 0; i < 8; i++) {
318 		if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0)
319 			break;
320 		printf("      driver %3u block: %u\n", i + 1, m[i].ddBlock);
321 		printf("        size in blocks: %u\n", m[i].ddSize);
322 		printf("           driver type: 0x%x\n", m[i].ddType);
323 	}
324 	printf("remainder of block -");
325 	dump_block(map->sbReserved, sizeof(map->sbReserved));
326 }
327 
328 int
329 get_max_type_string_length(struct partition_map *map)
330 {
331 	struct entry *entry;
332 	int max, length;
333 
334 	max = 0;
335 
336 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
337 		length = strnlen(entry->dpme->dpme_type, DPISTRLEN);
338 		if (length > max)
339 			max = length;
340 	}
341 
342 	return max;
343 }
344 
345 int
346 get_max_name_string_length(struct partition_map *map)
347 {
348 	struct entry *entry;
349 	int max, length;
350 
351 	max = 0;
352 
353 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
354 		length = strnlen(entry->dpme->dpme_name, DPISTRLEN);
355 		if (length > max)
356 			max = length;
357 	}
358 
359 	return max;
360 }
361 
362 int
363 get_max_base_or_length(struct partition_map *map)
364 {
365 	struct entry *entry;
366 	int max;
367 
368 	max = 0;
369 
370 	LIST_FOREACH(entry, &map->disk_order, disk_entry) {
371 		if (entry->dpme->dpme_pblock_start > max)
372 			max = entry->dpme->dpme_pblock_start;
373 		if (entry->dpme->dpme_pblocks > max)
374 			max = entry->dpme->dpme_pblocks;
375 		if (entry->dpme->dpme_lblock_start > max)
376 			max = entry->dpme->dpme_lblock_start;
377 		if (entry->dpme->dpme_lblocks > max)
378 			max = entry->dpme->dpme_lblocks;
379 	}
380 
381 	return max;
382 }
383 
384 void
385 adjust_value_and_compute_prefix(double *value, int *prefix)
386 {
387 	double bytes;
388 	int multiplier;
389 
390 	bytes = *value;
391 	if (bytes < 1024.0) {
392 		multiplier = ' ';
393 	} else {
394 		bytes = bytes / 1024.0;
395 		if (bytes < 1024.0) {
396 			multiplier = 'K';
397 		} else {
398 			bytes = bytes / 1024.0;
399 			if (bytes < 1024.0) {
400 				multiplier = 'M';
401 			} else {
402 				bytes = bytes / 1024.0;
403 				if (bytes < 1024.0) {
404 					multiplier = 'G';
405 				} else {
406 					bytes = bytes / 1024.0;
407 					multiplier = 'T';
408 				}
409 			}
410 		}
411 	}
412 	*value = bytes;
413 	*prefix = multiplier;
414 }
415