No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / ofppc / stand / ofwboot / rdb.c
blob8c5852677e07b6bafed3672d6bd0fbdd2134916a
1 /* $NetBSD: ofdev.c,v 1.16 2009/01/12 07:49:57 tsutsui Exp $ */
3 /*-
4 * Copyright (c) 2009 Frank Wille.
5 * All rights reserved.
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
11 * are met:
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>
36 #include "rdb.h"
39 static u_long
40 rdbchksum(void *bdata)
42 u_long *blp, cnt, val;
44 blp = bdata;
45 cnt = blp[1];
46 val = 0;
48 while (cnt--)
49 val += *blp++;
50 return val;
54 static struct adostype
55 getadostype(u_long dostype)
57 struct adostype adt;
58 u_long t3, b1;
60 t3 = dostype & 0xffffff00;
61 b1 = dostype & 0x000000ff;
63 adt.fstype = b1;
65 switch (t3) {
66 case DOST_NBR:
67 adt.archtype = ADT_NETBSDROOT;
68 return adt;
69 case DOST_NBS:
70 adt.archtype = ADT_NETBSDSWAP;
71 return adt;
72 case DOST_NBU:
73 adt.archtype = ADT_NETBSDUSER;
74 return adt;
75 case DOST_AMIX:
76 adt.archtype = ADT_AMIX;
77 if (b1 == 2)
78 adt.fstype = FS_BSDFFS;
79 else
80 adt.fstype = FS_UNUSED;
81 return adt;
82 case DOST_XXXBSD:
83 if (b1 == 'S') {
84 dostype = DOST_NBS;
85 dostype |= FS_SWAP;
86 } else {
87 if (b1 == 'R')
88 dostype = DOST_NBR;
89 else
90 dostype = DOST_NBU;
91 dostype |= FS_BSDFFS;
93 return getadostype(dostype);
94 case DOST_EXT2:
95 adt.archtype = ADT_EXT2;
96 adt.fstype = FS_EX2FS;
97 return adt;
98 case DOST_RAID:
99 adt.archtype = ADT_RAID;
100 adt.fstype = FS_RAID;
101 return adt;
102 default:
103 adt.archtype = ADT_UNKNOWN;
104 adt.fstype = FS_UNUSED;
105 return adt;
111 * Find a valid RDB disklabel.
114 search_rdb_label(struct of_dev *devp, char *buf, struct disklabel *lp)
116 struct adostype adt;
117 struct rdblock *rbp;
118 struct partblock *pbp;
119 struct disklabel *dlp;
120 struct partition *pp;
121 u_long blk;
122 size_t read;
123 int i;
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)
132 return ERDLAB;
134 /* check for valid RDB */
135 if (rbp->id == RDBLOCK_ID && rdbchksum(rbp) == 0)
136 break;
138 /* check for native NetBSD label */
139 dlp = (struct disklabel *)(buf + LABELOFFSET);
140 if (dlp->d_magic == DISKMAGIC && dkcksum(dlp) == 0) {
141 *lp = *dlp;
142 return 0;
145 if (blk == RDB_MAXBLOCKS)
146 return ERDLAB;
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;
165 else
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);
175 lp->d_rpm = 3600;
176 lp->d_interleave = rbp->interleave;
177 lp->d_headswitch = lp->d_flags = lp->d_trackskew = lp->d_cylskew = 0;
178 lp->d_trkseek = 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)
191 return ERDLAB;
193 /* verify ID and checksum of PART block */
194 if (pbp->id != PARTBLOCK_ID || rdbchksum(pbp))
195 return ERDLAB;
197 /* environment table in PART block needs at least 11 entries */
198 if (pbp->e.tabsize < 11)
199 return ERDLAB;
201 /* need a table size of 16 for a valid dostype */
202 if (pbp->e.tabsize < 16)
203 pbp->e.dostype = 0;
204 adt = getadostype(pbp->e.dostype);
206 /* determine partition index */
207 switch (adt.archtype) {
208 case ADT_NETBSDROOT:
209 pp = &lp->d_partitions[0];
210 if (pp->p_size)
211 continue;
212 break;
213 case ADT_NETBSDSWAP:
214 pp = &lp->d_partitions[1];
215 if (pp->p_size)
216 continue;
217 break;
218 default:
219 pp = &lp->d_partitions[lp->d_npartitions++];
220 break;
223 /* sort partitions after RAW_PART by offset */
224 while ((pp - lp->d_partitions) > RAW_PART + 1) {
225 daddr_t boff;
227 boff = pbp->e.lowcyl * pbp->e.secpertrk
228 * pbp->e.numheads
229 * ((pbp->e.sizeblock << 2) / lp->d_secsize);
230 if (boff > (pp - 1)->p_offset)
231 break;
232 *pp = *(pp - 1); /* struct copy */
233 pp--;
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
241 * pbp->e.numheads
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;
250 lp->d_checksum = 0;
251 lp->d_checksum = dkcksum(lp);
252 return 0;