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