1 /* $NetBSD: ofdev.c,v 1.16 2009/01/12 07:49:57 tsutsui Exp $ */
4 * Copyright (c) 2009 Frank Wille.
7 * Written by Frank Wille for The NetBSD Project.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/param.h>
32 #include <sys/disklabel_rdb.h>
34 #include <lib/libsa/stand.h>
40 rdbchksum(void *bdata
)
42 u_long
*blp
, cnt
, val
;
54 static struct adostype
55 getadostype(u_long dostype
)
60 t3
= dostype
& 0xffffff00;
61 b1
= dostype
& 0x000000ff;
67 adt
.archtype
= ADT_NETBSDROOT
;
70 adt
.archtype
= ADT_NETBSDSWAP
;
73 adt
.archtype
= ADT_NETBSDUSER
;
76 adt
.archtype
= ADT_AMIX
;
78 adt
.fstype
= FS_BSDFFS
;
80 adt
.fstype
= FS_UNUSED
;
93 return getadostype(dostype
);
95 adt
.archtype
= ADT_EXT2
;
96 adt
.fstype
= FS_EX2FS
;
99 adt
.archtype
= ADT_RAID
;
100 adt
.fstype
= FS_RAID
;
103 adt
.archtype
= ADT_UNKNOWN
;
104 adt
.fstype
= FS_UNUSED
;
111 * Find a valid RDB disklabel.
114 search_rdb_label(struct of_dev
*devp
, char *buf
, struct disklabel
*lp
)
118 struct partblock
*pbp
;
119 struct disklabel
*dlp
;
120 struct partition
*pp
;
126 * Scan the first RDB_MAXBLOCKS of a disk for an RDB block.
128 rbp
= (struct rdblock
*)buf
;
129 for (blk
= 0; blk
< RDB_MAXBLOCKS
; blk
++) {
130 if (strategy(devp
, F_READ
, blk
, DEV_BSIZE
, buf
, &read
)
131 || read
!= DEV_BSIZE
)
134 /* check for valid RDB */
135 if (rbp
->id
== RDBLOCK_ID
&& rdbchksum(rbp
) == 0)
138 /* check for native NetBSD label */
139 dlp
= (struct disklabel
*)(buf
+ LABELOFFSET
);
140 if (dlp
->d_magic
== DISKMAGIC
&& dkcksum(dlp
) == 0) {
145 if (blk
== RDB_MAXBLOCKS
)
148 /* Found RDB, clear disklabel partitions before reading PART blocks. */
149 lp
->d_npartitions
= RAW_PART
+ 1;
150 for (i
= 0; i
< MAXPARTITIONS
; i
++) {
151 lp
->d_partitions
[i
].p_size
= 0;
152 lp
->d_partitions
[i
].p_offset
= 0;
153 lp
->d_partitions
[i
].p_fstype
= 0;
157 * Construct a disklabel from RDB.
159 lp
->d_secsize
= rbp
->nbytes
;
160 lp
->d_nsectors
= rbp
->nsectors
;
161 lp
->d_ntracks
= rbp
->nheads
;
162 /* be prepared that rbp->ncylinders may be a bogus value */
163 if (rbp
->highcyl
== 0)
164 lp
->d_ncylinders
= rbp
->ncylinders
;
166 lp
->d_ncylinders
= rbp
->highcyl
+ 1;
167 /* also don't trust rbp->secpercyl */
168 lp
->d_secpercyl
= (rbp
->secpercyl
<= lp
->d_nsectors
* lp
->d_ntracks
) ?
169 rbp
->secpercyl
: lp
->d_nsectors
* lp
->d_ntracks
;
170 if (lp
->d_secpercyl
== 0)
171 lp
->d_secpercyl
= lp
->d_nsectors
* lp
->d_ntracks
;
173 lp
->d_secperunit
= lp
->d_secpercyl
* lp
->d_ncylinders
;
174 lp
->d_acylinders
= rbp
->ncylinders
- (rbp
->highcyl
- rbp
->lowcyl
+ 1);
176 lp
->d_interleave
= rbp
->interleave
;
177 lp
->d_headswitch
= lp
->d_flags
= lp
->d_trackskew
= lp
->d_cylskew
= 0;
180 /* raw partition gets the entire disk */
181 lp
->d_partitions
[RAW_PART
].p_size
= rbp
->ncylinders
* lp
->d_secpercyl
;
184 * Now scan for partition blocks.
186 pbp
= (struct partblock
*)buf
;
187 for (blk
= rbp
->partbhead
; blk
!= RDBNULL
; blk
= pbp
->next
) {
188 if (strategy(devp
, F_READ
, blk
* (lp
->d_secsize
/ DEV_BSIZE
),
189 lp
->d_secsize
, buf
, &read
)
190 || read
!= lp
->d_secsize
)
193 /* verify ID and checksum of PART block */
194 if (pbp
->id
!= PARTBLOCK_ID
|| rdbchksum(pbp
))
197 /* environment table in PART block needs at least 11 entries */
198 if (pbp
->e
.tabsize
< 11)
201 /* need a table size of 16 for a valid dostype */
202 if (pbp
->e
.tabsize
< 16)
204 adt
= getadostype(pbp
->e
.dostype
);
206 /* determine partition index */
207 switch (adt
.archtype
) {
209 pp
= &lp
->d_partitions
[0];
214 pp
= &lp
->d_partitions
[1];
219 pp
= &lp
->d_partitions
[lp
->d_npartitions
++];
223 /* sort partitions after RAW_PART by offset */
224 while ((pp
- lp
->d_partitions
) > RAW_PART
+ 1) {
227 boff
= pbp
->e
.lowcyl
* pbp
->e
.secpertrk
229 * ((pbp
->e
.sizeblock
<< 2) / lp
->d_secsize
);
230 if (boff
> (pp
- 1)->p_offset
)
232 *pp
= *(pp
- 1); /* struct copy */
236 /* get partition size, offset, fstype */
237 pp
->p_size
= (pbp
->e
.highcyl
- pbp
->e
.lowcyl
+ 1)
238 * pbp
->e
.secpertrk
* pbp
->e
.numheads
239 * ((pbp
->e
.sizeblock
<< 2) / lp
->d_secsize
);
240 pp
->p_offset
= pbp
->e
.lowcyl
* pbp
->e
.secpertrk
242 * ((pbp
->e
.sizeblock
<< 2) / lp
->d_secsize
);
243 pp
->p_fstype
= adt
.fstype
;
247 * All partitions have been found. The disklabel is valid.
249 lp
->d_magic
= lp
->d_magic2
= DISKMAGIC
;
251 lp
->d_checksum
= dkcksum(lp
);