Home | History | Annotate | Line # | Download | only in dist
      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