//
// dump.c - dumping partition maps
//
// Written by Eryk Vershen
//
/*
* Copyright 1996,1997,1998 by Apple Computer, Inc.
* All Rights Reserved
*
* Permission to use, copy, modify, and distribute this software and
* its documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appears in all copies and
* that both the copyright notice and this permission notice appear in
* supporting documentation.
*
* APPLE COMPUTER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE.
*
* IN NO EVENT SHALL APPLE COMPUTER BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
* NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
typedef struct PatchList {
uint16_t numPatchBlocks; // number of disk blocks to hold the patch list
uint16_t numPatches; // number of patches in list
PatchDescriptor thePatch[1];
} PatchList;
typedef PatchList *PatchListPtr;
//
// Global Variables
//
int aflag = AFLAG_DEFAULT; /* abbreviate partition types */
int pflag = PFLAG_DEFAULT; /* show physical limits of partition */
int fflag = FFLAG_DEFAULT; /* show HFS volume names */
//
// Forward declarations
//
void adjust_value_and_compute_prefix(double *value, int *prefix);
void dump_block_zero(partition_map_header *map);
void dump_partition_entry(partition_map *entry, int type_length, int name_length, int digits);
int get_max_base_or_length(partition_map_header *map);
int get_max_name_string_length(partition_map_header *map);
int get_max_type_string_length(partition_map_header *map);
//
// Routines
//
int
dump(char *name)
{
partition_map_header *map;
int junk;
map = open_partition_map(name, &junk, 0);
if (map == NULL) {
//error(-1, "No partition map in '%s'", name);
return 0;
}
dump_partition_map(map, 1);
close_partition_map(map);
return 1;
}
void
dump_block_zero(partition_map_header *map)
{
Block0 *p;
DDMap *m;
int i;
double value;
int prefix;
int32_t t;
p = map->misc;
if (p->sbSig != BLOCK0_SIGNATURE) {
return;
}
value = ((double)p->sbBlkCount) * p->sbBlkSize;
adjust_value_and_compute_prefix(&value, &prefix);
printf("\nDevice block size=%u, Number of Blocks=%"PRIu32" (%1.1f%c)\n",
p->sbBlkSize, p->sbBlkCount, value, prefix);
printf("DeviceType=0x%x, DeviceId=0x%x\n",
p->sbDevType, p->sbDevId);
if (p->sbDrvrCount > 0) {
printf("Drivers-\n");
m = (DDMap *) p->sbMap;
for (i = 0; i < p->sbDrvrCount; i++) {
printf("%u: %3u @ %"PRIu32", ", i+1,
m[i].ddSize, get_align_long(&m[i].ddBlock));
if (map->logical_block != p->sbBlkSize) {
t = (m[i].ddSize * p->sbBlkSize) / map->logical_block;
printf("(%"PRIu32"@", t);
t = (get_align_long(&m[i].ddBlock) * p->sbBlkSize)
/ map->logical_block;
printf("%"PRIu32") ", t);
}
printf("type=0x%x\n", m[i].ddType);
}
}
printf("\n");
}
void
dump_partition_map(partition_map_header *map, int disk_order)
{
partition_map * entry;
int max_type_length;
int max_name_length;
int digits;
char *alternate;
printf(" flags: 0x%"PRIx32"\n", (uint32_t)p->dpme_flags);
printf(" ");
if (dpme_valid_get(p)) printf("valid ");
if (dpme_allocated_get(p)) printf("alloc ");
if (dpme_in_use_get(p)) printf("in-use ");
if (dpme_bootable_get(p)) printf("boot ");
if (dpme_readable_get(p)) printf("read ");
if (dpme_writable_get(p)) printf("write ");
if (dpme_os_pic_code_get(p)) printf("pic ");
t = p->dpme_flags >> 7;
for (i = 7; i <= 31; i++) {
if (t & 0x1) {
printf("%d ", i);
}
t = t >> 1;
}
printf("\n");
printf(" signature: 0x%x\n", zp->sbSig);
printf(" size of a block: %d\n", zp->sbBlkSize);
printf(" number of blocks: %"PRId32"\n", zp->sbBlkCount);
printf(" device type: 0x%x\n", zp->sbDevType);
printf(" device id: 0x%x\n", zp->sbDevId);
printf(" data: 0x%"PRIx32"\n", zp->sbData);
printf(" driver count: %d\n", zp->sbDrvrCount);
m = (DDMap *) zp->sbMap;
for (i = 0; &m[i].ddType < &zp->sbMap[247]; i++) {
if (m[i].ddBlock == 0 && m[i].ddSize == 0 && m[i].ddType == 0) {
break;
}
printf(" driver %3u block: %"PRId32"\n", i+1, m[i].ddBlock);
printf(" size in blocks: %d\n", m[i].ddSize);
printf(" driver type: 0x%x\n", m[i].ddType);
}
printf("remainder of block -");
dump_block((uint8_t *)(void *)&m[i].ddBlock, (&zp->sbMap[247]-((uint16_t *)(void *)&m[i].ddBlock))*2);
}
void
display_patches(partition_map *entry)
{
long long offset;
MEDIA m;
static uint8_t *patch_block;
PatchListPtr p;
PatchDescriptorPtr q;
uint8_t *next;
uint8_t *s;
int i;
offset = entry->data->dpme_pblock_start;
m = entry->the_map->m;
offset = ((long long) entry->data->dpme_pblock_start) * entry->the_map->logical_block;
if (patch_block == NULL) {
patch_block = (uint8_t *) malloc(PBLOCK_SIZE);
if (patch_block == NULL) {
error(errno, "can't allocate memory for patch block buffer");
return;
}
}
if (read_media(m, (long long)offset, PBLOCK_SIZE, (char *)patch_block) == 0) {
error(errno, "Can't read patch block");
return;
}
p = (PatchListPtr) patch_block;
if (p->numPatchBlocks != 1) {
i = p->numPatchBlocks;
free(patch_block);
patch_block = (uint8_t *) malloc(PBLOCK_SIZE*i);
if (patch_block == NULL) {
error(errno, "can't allocate memory for patch blocks buffer");
return;
}
s = patch_block + PBLOCK_SIZE*i;
while (i > 0) {
s -= PBLOCK_SIZE;
i -= 1;
if (read_media(m, offset+i, PBLOCK_SIZE, (char *)s) == 0) {
error(errno, "Can't read patch block %d", i);
return;
}
}
p = (PatchListPtr) patch_block;
}
printf("Patch list (%d entries)\n", p->numPatches);
q = p->thePatch;
for (i = 0; i < p->numPatches; i++) {
printf("%2d signature: '%.4s'\n", i+1, (char *)&q->patchSig);
printf(" version: %d.%d\n", q->majorVers, q->minorVers);
printf(" flags: 0x%"PRIx32"\n", q->flags);
printf(" offset: %"PRId32"\n", q->patchOffset);
printf(" size: %"PRId32"\n", q->patchSize);
printf(" CRC: 0x%"PRIx32"\n", q->patchCRC);
printf(" name: '%.*s'\n", q->patchName[0], &q->patchName[1]);
printf(" vendor: '%.*s'\n", q->patchVendor[0], &q->patchVendor[1]);
next = ((uint8_t *)q) + q->patchDescriptorLen;
s = &q->patchVendor[q->patchVendor[0]+1];
if (next > s) {
printf("remainder of entry -");
dump_block(s, next-s);
}
q = (PatchDescriptorPtr)next;
}
}
int
get_max_type_string_length(partition_map_header *map)
{
partition_map * entry;
int max;
int length;
if (map == NULL) {
return 0;
}
max = 0;
for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
length = strnlen(entry->data->dpme_type, DPISTRLEN);
if (length > max) {
max = length;
}
}
return max;
}
int
get_max_name_string_length(partition_map_header *map)
{
partition_map * entry;
int max;
int length;
if (map == NULL) {
return 0;
}
max = 0;
for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
length = strnlen(entry->data->dpme_name, DPISTRLEN);
if (length > max) {
max = length;
}
if (fflag) {
if (entry->HFS_name == NULL) {
length = 0;
} else {
length = strlen(entry->HFS_name) + 2;
}
if (length > max) {
max = length;
}
}
}
return max;
}
int
get_max_base_or_length(partition_map_header *map)
{
partition_map * entry;
uint32_t max;
if (map == NULL) {
return 0;
}
max = 0;
for (entry = map->disk_order; entry != NULL; entry = entry->next_on_disk) {
if (entry->data->dpme_pblock_start > max) {
max = entry->data->dpme_pblock_start;
}
if (entry->data->dpme_pblocks > max) {
max = entry->data->dpme_pblocks;
}
if (entry->data->dpme_lblock_start > max) {
max = entry->data->dpme_lblock_start;
}
if (entry->data->dpme_lblocks > max) {
max = entry->data->dpme_lblocks;
}
}
return max;
}
void
adjust_value_and_compute_prefix(double *value, int *prefix)
{
double bytes;
int multiplier;