1 /* $NetBSD: disklbl.c,v 1.5 2009/03/14 15:36:04 dsl Exp $ */
4 * Copyright (c) 1995 Waldi Ravens.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Waldi Ravens.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/types.h>
41 static int dkcksum
PROTO((struct disklabel
*));
42 static int bsd_label
PROTO((disk_t
*, u_int
));
43 static int ahdi_label
PROTO((disk_t
*));
44 static int ahdi_display
PROTO((disk_t
*));
45 static u_int ahdi_getparts
PROTO((disk_t
*, u_int
, u_int
));
48 readdisklabel(disk_t
*dd
)
52 printf("Device : %s (%s) [%s]\n", dd
->sname
, dd
->fname
,
54 printf("Medium size: %lu sectors\n", (u_long
)dd
->msize
);
55 printf("Sector size: %lu bytes\n\n", (u_long
)dd
->bsize
);
57 e
= bsd_label(dd
, LABELSECTOR
);
59 printf("Device I/O error (hardware problem?)\n\n");
63 printf("NetBSD/Atari format, boot block: "
64 "sector %u labeloffset %u\n\n",
65 dd
->bblock
, dd
->lblofs
);
71 printf("Device I/O error (hardware problem?)\n\n");
75 printf("AHDI format, NetBSD boot block: ");
76 if (dd
->bblock
!= NO_BOOT_BLOCK
)
77 printf("sector %u labeloffset %u\n\n",
78 dd
->bblock
, dd
->lblofs
);
79 else printf("none\n\n");
83 printf("Unknown label format.\n\n");
88 bsd_label(disk_t
*dd
, u_int offset
)
94 nsec
= (BBMINSIZE
+ (dd
->bsize
- 1)) / dd
->bsize
;
95 bblk
= disk_read(dd
, offset
, nsec
);
99 end
= (u_int
*)&bblk
[BBMINSIZE
- sizeof(struct disklabel
)];
101 for (p
= (u_int
*)bblk
; p
< end
; ++p
) {
102 struct disklabel
*dl
= (struct disklabel
*)&p
[1];
103 if ( ( (p
[0] == NBDAMAGIC
&& offset
== 0)
104 || (p
[0] == AHDIMAGIC
&& offset
!= 0)
105 || (u_char
*)dl
- bblk
== 7168
107 && dl
->d_npartitions
<= MAXPARTITIONS
108 && dl
->d_magic2
== DISKMAGIC
109 && dl
->d_magic
== DISKMAGIC
112 dd
->lblofs
= (u_char
*)dl
- bblk
;
126 dkcksum(struct disklabel
*dl
)
128 u_short
*start
, *end
, sum
= 0;
130 start
= (u_short
*)dl
;
131 end
= (u_short
*)&dl
->d_partitions
[dl
->d_npartitions
];
138 ahdi_label(disk_t
*dd
)
144 * The AHDI format requires a specific block size.
146 if (dd
->bsize
!= AHDI_BSIZE
)
150 * Fetch the AHDI partition descriptors.
152 i
= ahdi_getparts(dd
, AHDI_BBLOCK
, AHDI_BBLOCK
);
155 return(-1); /* disk read error */
156 else return(1); /* reading past end of medium */
160 * Display and perform sanity checks.
162 i
= ahdi_display(dd
);
167 * Search for a NetBSD disk label
169 dd
->bblock
= NO_BOOT_BLOCK
;
170 for (i
= 0; i
< dd
->nparts
; ++i
) {
171 part_t
*pd
= &dd
->parts
[i
];
172 u_int id
= *((u_int32_t
*)&pd
->id
) >> 8;
173 if (id
== AHDI_PID_NBD
|| id
== AHDI_PID_RAW
) {
174 u_int offs
= pd
->start
;
175 if ((e
= bsd_label(dd
, offs
)) < 0) {
176 return(e
); /* I/O error */
179 dd
->bblock
= offs
; /* got it */
182 if (id
== AHDI_PID_NBD
&& dd
->bblock
== NO_BOOT_BLOCK
)
190 root_cmp(const void *x1
, const void *x2
)
192 const u_int
*r1
= x1
,
203 part_cmp(const void *x1
, const void *x2
)
205 const part_t
*p1
= x1
,
208 if (p1
->start
< p2
->start
)
210 if (p1
->start
> p2
->start
)
212 if (p1
->end
< p2
->end
)
214 if (p1
->end
> p2
->end
)
216 if (p1
->rsec
< p2
->rsec
)
218 if (p1
->rsec
> p2
->rsec
)
220 if (p1
->rent
< p2
->rent
)
222 if (p1
->rent
> p2
->rent
)
228 ahdi_display(disk_t
*dd
)
232 printf("Start of bad sector list : %u\n", dd
->bslst
);
233 if (dd
->bslst
== 0) {
234 printf("* Illegal value (zero) *\n"); rv
= 1;
236 printf("End of bad sector list : %u\n", dd
->bslend
);
237 if (dd
->bslend
== 0) {
238 printf("* Illegal value (zero) *\n"); rv
= 1;
240 printf("Medium size (in root sec): %u\n", dd
->hdsize
);
241 if (dd
->hdsize
== 0) {
242 printf("* Illegal value (zero) *\n"); rv
= 1;
245 qsort(dd
->roots
, dd
->nroots
, sizeof *dd
->roots
, root_cmp
);
246 qsort(dd
->parts
, dd
->nparts
, sizeof *dd
->parts
, part_cmp
);
247 printf("\n root desc id start end MBs\n");
249 for (i
= 0; i
< dd
->nparts
; ++i
) {
250 part_t
*p1
= &dd
->parts
[i
];
251 u_int megs
= p1
->end
- p1
->start
+ 1,
252 blpm
= (1024 * 1024) / dd
->bsize
;
253 megs
= (megs
+ (blpm
>> 1)) / blpm
;
254 printf("%8u %4u %s %8u %8u (%3u)\n",
255 p1
->rsec
, p1
->rent
, p1
->id
,
256 p1
->start
, p1
->end
, megs
);
257 for (j
= 0; j
< dd
->nroots
; ++j
) {
258 u_int aux
= dd
->roots
[j
];
259 if (aux
>= p1
->start
&& aux
<= p1
->end
) {
260 printf("FATAL: auxiliary root at %u\n", aux
);
265 part_t
*p2
= &dd
->parts
[j
];
266 if (p1
->start
>= p2
->start
&& p1
->start
<= p2
->end
) {
267 printf("FATAL: clash with %u/%u\n", p2
->rsec
, p2
->rent
);
270 if (p2
->start
>= p1
->start
&& p2
->start
<= p1
->end
) {
271 printf("FATAL: clash with %u/%u\n", p2
->rsec
, p2
->rent
);
275 if (p1
->start
>= dd
->bslst
&& p1
->start
<= dd
->bslend
) {
276 printf("FATAL: partition overlaps with bad sector list\n");
279 if (dd
->bslst
>= p1
->start
&& dd
->bslst
<= p1
->end
) {
280 printf("FATAL: partition overlaps with bad sector list\n");
285 printf("\nTotal number of auxiliary roots: %u\n", dd
->nroots
);
286 printf("Total number of partitions : %u\n", dd
->nparts
);
287 if (dd
->nparts
== 0) {
288 printf("* Weird # of partitions (zero) *\n"); rv
= 1;
290 if (dd
->nparts
> AHDI_MAXPARTS
) {
291 printf("* Too many AHDI partitions for the default NetBSD "
292 "kernel *\n Increase MAXAUXROOTS in src/sys/arch/"
293 "atari/include/disklabel.h\n to at least %u, and "
294 "recompile the NetBSD kernel.\n", dd
->nroots
);
301 ahdi_getparts(dd
, rsec
, esec
)
306 struct ahdi_part
*part
, *end
;
307 struct ahdi_root
*root
;
310 root
= disk_read(dd
, rsec
, 1);
312 rv
= rsec
+ (rsec
== 0);
316 if (rsec
== AHDI_BBLOCK
)
317 end
= &root
->ar_parts
[AHDI_MAXRPD
];
318 else end
= &root
->ar_parts
[AHDI_MAXARPD
];
319 for (part
= root
->ar_parts
; part
< end
; ++part
) {
320 u_int id
= *((u_int32_t
*)&part
->ap_flg
);
321 if (!(id
& 0x01000000))
323 if ((id
&= 0x00ffffff) == AHDI_PID_XGM
) {
324 u_int offs
= part
->ap_offs
+ esec
;
325 u_int i
= ++dd
->nroots
;
326 dd
->roots
= xrealloc(dd
->roots
, i
* sizeof *dd
->roots
);
327 dd
->roots
[--i
] = offs
;
328 rv
= ahdi_getparts(dd
, offs
,
329 esec
== AHDI_BBLOCK
? offs
: esec
);
334 u_int i
= ++dd
->nparts
;
335 dd
->parts
= xrealloc(dd
->parts
, i
* sizeof *dd
->parts
);
337 *((u_int32_t
*)&p
->id
) = id
<< 8;
338 p
->start
= part
->ap_offs
+ rsec
;
339 p
->end
= p
->start
+ part
->ap_size
- 1;
341 p
->rent
= part
- root
->ar_parts
;
344 dd
->hdsize
= root
->ar_hdsize
;
345 dd
->bslst
= root
->ar_bslst
;
346 dd
->bslend
= root
->ar_bslst
+ root
->ar_bslsize
- 1;