4 // Written by Eryk Vershen
8 * Copyright 1997,1998 by Apple Computer, Inc.
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.
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.
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.
31 // for malloc(), free()
43 #include "deblock_media.h"
65 struct range_list
*next
;
66 struct range_list
*prev
;
67 enum range_state state
;
72 typedef struct range_list range_list
;
86 static partition_map_header
*the_map
;
87 static MEDIA the_media
;
92 // Forward declarations
94 int get_block_zero(void);
95 int get_block_n(int n
);
96 range_list
*new_range_list_item(enum range_state state
, int valid
, u32 low
, u32 high
);
97 void initialize_list(range_list
**list
);
98 void add_range(range_list
**list
, u32 base
, u32 len
, int allocate
);
99 void print_range_list(range_list
*list
);
100 void delete_list(range_list
*list
);
101 void coalesce_list(range_list
*list
);
112 if (the_map
!= NULL
) {
116 if (read_media(the_media
, (long long) 0, PBLOCK_SIZE
, buffer
) == 0) {
119 b0
= (Block0
*) buffer
;
120 convert_block0(b0
, 1);
131 partition_map
* entry
;
134 if (the_map
!= NULL
) {
135 entry
= find_entry_by_disk_address(n
, the_map
);
143 if (read_media(the_media
, ((long long) n
) * g
, PBLOCK_SIZE
, (void *)buffer
) == 0) {
146 mb
= (DPME
*) buffer
;
156 new_range_list_item(enum range_state state
, int valid
, u32 low
, u32 high
)
160 item
= (range_list
*) malloc(sizeof(struct range_list
));
172 initialize_list(range_list
**list
)
176 item
= new_range_list_item(kUnallocated
, 0, 0, 0xFFFFFFFF);
182 delete_list(range_list
*list
)
187 for (cur
= list
; cur
!= 0; ) {
196 add_range(range_list
**list
, u32 base
, u32 len
, int allocate
)
203 if (list
== 0 || *list
== 0) {
204 /* XXX initialized list will always have one element */
209 high
= base
+ len
- 1;
210 if (len
== 0 || high
< len
- 1) {
211 /* XXX wrapped around */
216 while (low
<= high
) {
218 /* XXX should never occur */
221 if (low
<= cur
->end
) {
222 if (cur
->start
< low
) {
223 item
= new_range_list_item(cur
->state
, cur
->valid
, cur
->start
, low
-1);
224 /* insert before here */
225 if (cur
->prev
== 0) {
229 item
->prev
= cur
->prev
;
230 item
->prev
->next
= item
;
237 if (high
< cur
->end
) {
238 item
= new_range_list_item(cur
->state
, cur
->valid
, high
+1, cur
->end
);
239 /* insert after here */
240 if (cur
->next
== 0) {
243 item
->next
= cur
->next
;
244 item
->next
->prev
= item
;
253 switch (cur
->state
) {
255 cur
->state
= kAllocated
;
258 case kMultiplyAllocated
:
259 cur
->state
= kMultiplyAllocated
;
273 coalesce_list(range_list
*list
)
278 for (cur
= list
; cur
!= 0; ) {
283 if (cur
->valid
== item
->valid
284 && cur
->state
== item
->state
) {
285 cur
->end
= item
->end
;
286 cur
->next
= item
->next
;
287 if (item
->next
!= 0) {
288 item
->next
->prev
= cur
;
299 print_range_list(range_list
*list
)
305 s
= NULL
; /* XXXGCC -Wuninitialized [powerpc] */
308 printf("Empty range list\n");
311 printf("Range list:\n");
313 for (cur
= list
; cur
!= 0; cur
= cur
->next
) {
315 switch (cur
->state
) {
323 case kMultiplyAllocated
:
324 s
= "multiply allocated";
328 printf("\t%lu:%lu %s\n", cur
->start
, cur
->end
, s
);
330 switch (cur
->state
) {
338 case kMultiplyAllocated
:
339 s
= "multiply allocated";
343 printf("\t%lu:%lu out of range, but %s\n", cur
->start
, cur
->end
, s
);
353 validate_map(partition_map_header
*map
)
361 //printf("Validation not implemented yet.\n");
365 if (get_string_argument("Name of device: ", &name
, 1) == 0) {
366 bad_input("Bad name");
369 the_media
= open_pathname_as_media(name
, O_RDONLY
);
370 if (the_media
== 0) {
371 error(errno
, "can't open file '%s'", name
);
375 g
= media_granularity(the_media
);
376 if (g
< PBLOCK_SIZE
) {
379 the_media
= open_deblock_media(PBLOCK_SIZE
, the_media
);
381 buffer
= malloc(PBLOCK_SIZE
);
382 if (buffer
== NULL
) {
383 error(errno
, "can't allocate memory for disk buffer");
390 g
= map
->logical_block
;
393 initialize_list(&list
);
396 if (get_block_zero() == 0) {
397 printf("unable to read block 0\n");
400 // XXX signature valid
401 // XXX size & count match DeviceCapacity
402 // XXX number of descriptors matches array size
403 // XXX each descriptor wholly contained in a partition
404 // XXX the range below here is in physical blocks but the map is in logical blocks!!!
405 add_range(&list
, 1, b0
->sbBlkCount
-1, 0); /* subtract one since args are base & len */
408 // compute size of map
410 limit
= the_map
->blocks_in_map
;
412 if (get_block_n(1) == 0) {
413 printf("unable to get first block\n");
416 if (mb
->dpme_signature
!= DPME_SIGNATURE
) {
419 limit
= mb
->dpme_map_entries
;
428 /* XXX what to use for end of list? */
438 printf("block %d:\n", i
);
441 if (get_block_n(i
) == 0) {
442 printf("\tunable to get\n");
443 goto post_processing
;
448 if (mb
->dpme_signature
!= DPME_SIGNATURE
) {
450 printf("\tsignature is 0x%x, should be 0x%x\n", mb
->dpme_signature
, DPME_SIGNATURE
);
453 if (mb
->dpme_reserved_1
!= 0) {
455 printf("\treserved word is 0x%x, should be 0\n", mb
->dpme_reserved_1
);
457 // entry count matches
461 printf("\tentry count is 0x%lx, real value unknown\n", mb
->dpme_map_entries
);
464 if (mb
->dpme_map_entries
!= limit
) {
466 printf("\tentry count is 0x%lx, should be %ld\n", mb
->dpme_map_entries
, limit
);
468 // lblocks contained within physical
469 if (mb
->dpme_lblock_start
>= mb
->dpme_pblocks
470 || mb
->dpme_lblocks
> mb
->dpme_pblocks
- mb
->dpme_lblock_start
) {
472 printf("\tlogical blocks (%ld for %ld) not within physical size (%ld)\n",
473 mb
->dpme_lblock_start
, mb
->dpme_lblocks
, mb
->dpme_pblocks
);
475 // remember stuff for post processing
476 add_range(&list
, mb
->dpme_pblock_start
, mb
->dpme_pblocks
, 1);
478 // XXX type is known type?
479 // XXX no unknown flags?
480 // XXX boot blocks either within or outside of logical
481 // XXX checksum matches contents
482 // XXX other fields zero if boot_bytes is zero
483 // XXX processor id is known value?
484 // XXX no data in reserved3
491 // properties of whole map
493 // every block on disk in one & only one partition
495 print_range_list(list
);
496 // there is a partition for the map
497 // map fits within partition that contains it
499 // try to detect 512/2048 mixed partition map?
503 close_media(the_media
);