1 /* $NetBSD: disklabel.c,v 1.4 2009/03/14 14:45:57 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>
34 #include <sys/param.h>
35 #include <ufs/ufs/dinode.h>
36 #include <ufs/ffs/fs.h>
37 #include <sys/disklabel.h>
38 #include <machine/ahdilabel.h>
45 #if (BBSIZE < MINBBSIZE)
46 #error BBSIZE is smaller than MINBBSIZE
56 struct ahdi_part
*parts
;
59 u_int
dkcksum(struct disklabel
*);
60 u_int32_t
readdisklabel(char *, struct disklabel
*);
62 static int bsd_label(int, off_t
, struct disklabel
*);
63 static int ahdi_label(int, u_int32_t
*, struct disklabel
*);
64 static int ahdi_getparts(int, daddr_t
, daddr_t
, struct ahdilabel
*);
67 dkcksum (struct disklabel
*dl
)
70 *st
= (u_int16_t
*)dl
,
71 *end
= (u_int16_t
*)&dl
->d_partitions
[dl
->d_npartitions
];
79 readdisklabel (char *fn
, struct disklabel
*dl
)
84 memset(dl
, 0, sizeof *dl
);
86 if ((fd
= open(fn
, O_RDONLY
)) < 0)
87 err(EXIT_FAILURE
, "%s", fn
);
89 /* Try NetBSD/Atari format first */
90 if ((e
= bsd_label(fd
, (off_t
)0, dl
)) < 0)
91 err(EXIT_FAILURE
, "%s", fn
);
95 /* Try unprotected AHDI format last */
96 if ((e
= ahdi_label(fd
, &bbsec
, dl
)) < 0)
97 err(EXIT_FAILURE
, "%s", fn
);
101 warnx("%s: Unknown disk label format.", fn
);
102 return(NO_BOOT_BLOCK
);
106 bsd_label (int fd
, off_t offs
, struct disklabel
*label
)
111 if (lseek(fd
, offs
, SEEK_SET
) != offs
)
113 if (read(fd
, &bb
, sizeof(bb
)) != sizeof(bb
))
116 p
= (struct disklabel
*)bb
.bb_label
;
117 if ( (offs
== 0 && bb
.bb_magic
!= NBDAMAGIC
)
118 || (offs
!= 0 && bb
.bb_magic
!= AHDIMAGIC
)
119 || p
->d_npartitions
> MAXPARTITIONS
120 || p
->d_magic2
!= DISKMAGIC
121 || p
->d_magic
!= DISKMAGIC
132 ahdi_label (int fd
, u_int32_t
*bbsec
, struct disklabel
*label
)
138 memset(&al
, 0, sizeof(al
));
139 if ((e
= ahdi_getparts(fd
, AHDI_BBLOCK
, AHDI_BBLOCK
, &al
)))
143 * Perform sanity checks.
145 if (al
.bslst
== 0 || al
.bslend
== 0)
147 if (al
.nsecs
== 0 || al
.nparts
== 0)
149 if (al
.nparts
> AHDI_MAXPARTS
)
150 warnx("Too many AHDI partitions (%u).", al
.nparts
);
151 for (i
= 0; i
< al
.nparts
; ++i
) {
152 struct ahdi_part
*p1
= &al
.parts
[i
];
153 for (j
= 0; j
< al
.nroots
; ++j
) {
154 daddr_t aux
= al
.roots
[j
];
155 if (aux
>= p1
->ap_st
&& aux
<= p1
->ap_end
)
158 for (j
= i
+ 1; j
< al
.nparts
; ++j
) {
159 struct ahdi_part
*p2
= &al
.parts
[j
];
160 if (p1
->ap_st
>= p2
->ap_st
&& p1
->ap_st
<= p2
->ap_end
)
162 if (p2
->ap_st
>= p1
->ap_st
&& p2
->ap_st
<= p1
->ap_end
)
165 if (p1
->ap_st
>= al
.bslst
&& p1
->ap_st
<= al
.bslend
)
167 if (al
.bslst
>= p1
->ap_st
&& al
.bslst
<= p1
->ap_end
)
172 * Search for a NetBSD boot block
174 for (i
= 0; i
< al
.nparts
; ++i
) {
175 struct ahdi_part
*pd
= &al
.parts
[i
];
176 u_int id
= *((u_int32_t
*)&pd
->ap_flg
);
178 if (id
== AHDI_PID_NBD
|| id
== AHDI_PID_RAW
) {
179 off_t offs
= pd
->ap_st
* AHDI_BSIZE
;
180 if ((e
= bsd_label(fd
, offs
, label
)) < 0)
183 *bbsec
= pd
->ap_st
; /* got it */
188 *bbsec
= NO_BOOT_BLOCK
; /* AHDI label, no NetBSD boot block */
193 ahdi_getparts(fd
, rsec
, esec
, alab
)
197 struct ahdilabel
*alab
;
199 struct ahdi_part
*part
, *end
;
200 struct ahdi_root root
;
203 ro
= rsec
* AHDI_BSIZE
;
204 if (lseek(fd
, ro
, SEEK_SET
) != ro
) {
205 off_t mend
= lseek(fd
, 0, SEEK_END
);
206 if (mend
== -1 || mend
> ro
)
210 if (read(fd
, &root
, sizeof(root
)) != sizeof(root
))
213 if (rsec
== AHDI_BBLOCK
)
214 end
= &root
.ar_parts
[AHDI_MAXRPD
];
215 else end
= &root
.ar_parts
[AHDI_MAXARPD
];
216 for (part
= root
.ar_parts
; part
< end
; ++part
) {
217 u_int id
= *((u_int32_t
*)&part
->ap_flg
);
218 if (!(id
& 0x01000000))
220 if ((id
&= 0x00ffffff) == AHDI_PID_XGM
) {
222 daddr_t aux
= part
->ap_st
+ esec
;
223 alab
->roots
= realloc(alab
->roots
,
224 (alab
->nroots
+ 1) * sizeof(*alab
->roots
));
225 alab
->roots
[alab
->nroots
++] = aux
;
226 e
= ahdi_getparts(fd
, aux
,
227 esec
== AHDI_BBLOCK
? aux
: esec
, alab
);
232 alab
->parts
= realloc(alab
->parts
,
233 (alab
->nparts
+ 1) * sizeof(*alab
->parts
));
234 p
= &alab
->parts
[alab
->nparts
++];
235 *((u_int32_t
*)&p
->ap_flg
) = id
;
236 p
->ap_st
= part
->ap_st
+ rsec
;
237 p
->ap_end
= p
->ap_st
+ part
->ap_size
- 1;
240 alab
->nsecs
= root
.ar_hdsize
;
241 alab
->bslst
= root
.ar_bslst
;
242 alab
->bslend
= root
.ar_bslst
+ root
.ar_bslsize
- 1;