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