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