xref: /netbsd-src/sys/arch/luna68k/luna68k/disksubr.c (revision 4b552d31e19902d717589952b1ae158ab04f16fa)
1 /* $NetBSD: disksubr.c,v 1.34 2023/01/15 05:08:33 tsutsui Exp $ */
2 
3 /*
4  * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * Credits:
32  * This file was based mostly on the i386/disksubr.c file:
33  *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
34  * The functions: disklabel_sun_to_bsd, disklabel_bsd_to_sun
35  * were originally taken from arch/sparc/scsi/sun_disklabel.c
36  * (which was written by Theo de Raadt) and then substantially
37  * rewritten by Gordon W. Ross.
38  */
39 
40 /*
41  * Copyright (c) 1994 Theo de Raadt.  All rights reserved.
42  *
43  * Redistribution and use in source and binary forms, with or without
44  * modification, are permitted provided that the following conditions
45  * are met:
46  * 1. Redistributions of source code must retain the above copyright
47  *    notice, this list of conditions and the following disclaimer.
48  * 2. Redistributions in binary form must reproduce the above copyright
49  *    notice, this list of conditions and the following disclaimer in the
50  *    documentation and/or other materials provided with the distribution.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
53  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
54  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
55  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
56  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
57  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
58  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
59  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
61  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62  *
63  */
64 
65 /*
66  * Copyright (c) 1994, 1995 Gordon W. Ross
67  *
68  * Redistribution and use in source and binary forms, with or without
69  * modification, are permitted provided that the following conditions
70  * are met:
71  * 1. Redistributions of source code must retain the above copyright
72  *    notice, this list of conditions and the following disclaimer.
73  * 2. Redistributions in binary form must reproduce the above copyright
74  *    notice, this list of conditions and the following disclaimer in the
75  *    documentation and/or other materials provided with the distribution.
76  * 3. All advertising materials mentioning features or use of this software
77  *    must display the following acknowledgement:
78  *	This product includes software developed by the University of
79  *	California, Berkeley and its contributors.
80  * 4. Neither the name of the University nor the names of its contributors
81  *    may be used to endorse or promote products derived from this software
82  *    without specific prior written permission.
83  *
84  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
85  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
86  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
87  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
88  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
89  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
90  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
91  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
92  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
93  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
94  * SUCH DAMAGE.
95  *
96  * Credits:
97  * This file was based mostly on the i386/disksubr.c file:
98  *	@(#)ufs_disksubr.c	7.16 (Berkeley) 5/4/91
99  * The functions: disklabel_sun_to_bsd, disklabel_bsd_to_sun
100  * were originally taken from arch/sparc/scsi/sun_disklabel.c
101  * (which was written by Theo de Raadt) and then substantially
102  * rewritten by Gordon W. Ross.
103  */
104 
105 #include <sys/cdefs.h>
106 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.34 2023/01/15 05:08:33 tsutsui Exp $");
107 
108 #include <sys/param.h>
109 #include <sys/systm.h>
110 #include <sys/buf.h>
111 #include <sys/device.h>
112 #include <sys/disklabel.h>
113 #include <sys/disk.h>
114 #include <sys/dkbad.h>
115 
116 #include <dev/sun/disklabel.h>
117 
118 /*
119  * UniOS disklabel (== ISI disklabel) is very similar to SunOS.
120  *	SunOS				UniOS/ISI
121  *	text		128			128
122  *	(pad)		292			294
123  *	rpm		2		-
124  *	pcyl		2		badchk	2
125  *	sparecyl	2		maxblk	4
126  *	(pad)		4		dtype	2
127  *	interleave	2		ndisk	2
128  *	ncyl		2			2
129  *	acyl		2			2
130  *	ntrack		2			2
131  *	nsect		2			2
132  *	(pad)		4		bhead	2
133  *	-				ppart	2
134  *	dkpart[8]	64			64
135  *	magic		2			2
136  *	cksum		2			2
137  *
138  * Magic number value and checksum calculation are identical.  Subtle
139  * difference is partition start address; UniOS/ISI maintains sector
140  * numbers while SunOS label has cylinder number.
141  *
142  * It is found that LUNA Mach2.5 has BSD label embedded at offset 64
143  * retaining UniOS/ISI label at the end of label block.  LUNA Mach
144  * manipulates BSD disklabel in the same manner as 4.4BSD.  It's
145  * uncertain LUNA Mach can create a disklabel on fresh disks since
146  * Mach writedisklabel logic seems to fail when no BSD label is found.
147  *
148  * Kernel handles disklabel in this way;
149  *	- searches BSD label at offset 64
150  *	- if not found, searches UniOS/ISI label at the end of block
151  *	- kernel can distinguish whether it was SunOS label or UniOS/ISI
152  *	  label and understand both
153  *	- kernel writes UniOS/ISI label combined with BSD label to update
154  *	  the label block
155  */
156 
157 #if LABELSECTOR != 0
158 #error	"Default value of LABELSECTOR no longer zero?"
159 #endif
160 
161 static const char *disklabel_om_to_bsd(char *, struct disklabel *);
162 static int disklabel_bsd_to_om(struct disklabel *, char *);
163 
164 /*
165  * Attempt to read a disk label from a device
166  * using the indicated strategy routine.
167  * The label must be partly set up before this:
168  * secpercyl, secsize and anything required for a block i/o read
169  * operation in the driver's strategy/start routines
170  * must be filled in before calling us.
171  *
172  * Return buffer for use in signalling errors if requested.
173  *
174  * Returns null on success and an error string on failure.
175  */
176 const char *
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)177 readdisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp)
178 {
179 	struct buf *bp;
180 	struct disklabel *dlp;
181 	struct sun_disklabel *slp;
182 	int error;
183 	int i;
184 
185 	/* minimal requirements for archtypal disk label */
186 	if (lp->d_secperunit == 0)
187 		lp->d_secperunit = 0x1fffffff;
188 	if (lp->d_npartitions < RAW_PART + 1)
189 		lp->d_npartitions = RAW_PART + 1;
190 	for (i = 0; i < RAW_PART; i++) {
191 		lp->d_partitions[i].p_size = 0;
192 		lp->d_partitions[i].p_offset = 0;
193 	}
194 	if (lp->d_partitions[RAW_PART].p_size == 0)
195 		lp->d_partitions[RAW_PART].p_size = lp->d_secperunit;
196 	lp->d_partitions[RAW_PART].p_offset = 0;
197 
198 	/* obtain buffer to probe drive with */
199 	bp = geteblk((int)lp->d_secsize);
200 
201 	/* next, dig out disk label */
202 	bp->b_dev = dev;
203 	bp->b_blkno = LABELSECTOR;
204 	bp->b_cylinder = 0;
205 	bp->b_bcount = lp->d_secsize;
206 	bp->b_flags |= B_READ;
207 	(*strat)(bp);
208 
209 	/* if successful, locate disk label within block and validate */
210 	error = biowait(bp);
211 	if (!error) {
212 		/* Save the whole block in case it has info we need. */
213 		memcpy(clp->cd_block, bp->b_data, sizeof(clp->cd_block));
214 	}
215 	brelse(bp, 0);
216 	if (error)
217 		return ("disk label read error");
218 
219 	/* Check for a NetBSD disk label first. */
220 	dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET);
221 	if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC) {
222 		if (dkcksum(dlp) == 0) {
223 			*lp = *dlp;	/* struct assignment */
224 			return (NULL);
225 		}
226 		printf("NetBSD disk label corrupted");
227 	}
228 
229 	/* Check for a UniOS/ISI disk label. */
230 	slp = (struct sun_disklabel *)clp->cd_block;
231 	if (slp->sl_magic == SUN_DKMAGIC) {
232 		return (disklabel_om_to_bsd(clp->cd_block, lp));
233 	}
234 
235 	memset(clp->cd_block, 0, sizeof(clp->cd_block));
236 	return ("no disk label");
237 }
238 
239 /*
240  * Write disk label back to device after modification.
241  * Current label is already in clp->cd_block[]
242  */
243 int
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,struct cpu_disklabel * clp)244 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp, struct cpu_disklabel *clp)
245 {
246 	struct buf *bp;
247 	struct disklabel *dlp;
248 	int error;
249 
250 	/* implant NetBSD disklabel at LABELOFFSET. */
251 	dlp = (struct disklabel *)(clp->cd_block + LABELOFFSET);
252 	*dlp = *lp;	/* struct assignment */
253 
254 	error = disklabel_bsd_to_om(lp, clp->cd_block);
255 	if (error)
256 		return (error);
257 
258 	/* Get a buffer and copy the new label into it. */
259 	bp = geteblk((int)lp->d_secsize);
260 	memcpy(bp->b_data, clp->cd_block, sizeof(clp->cd_block));
261 
262 	/* Write out the updated label. */
263 	bp->b_dev = dev;
264 	bp->b_blkno = LABELSECTOR;
265 	bp->b_cylinder = 0;
266 	bp->b_bcount = lp->d_secsize;
267 	bp->b_flags |= B_WRITE;
268 	(*strat)(bp);
269 	error = biowait(bp);
270 	brelse(bp, 0);
271 
272 	return (error);
273 }
274 
275 /************************************************************************
276  *
277  * The rest of this was taken from arch/sparc/scsi/sun_disklabel.c
278  * and then substantially rewritten by Gordon W. Ross
279  *
280  ************************************************************************/
281 
282 /* What partition types to assume for Sun disklabels: */
283 static u_char
284 sun_fstypes[8] = {
285 	FS_BSDFFS,	/* a */
286 	FS_SWAP,	/* b */
287 	FS_OTHER,	/* c - whole disk */
288 	FS_BSDFFS,	/* d */
289 	FS_BSDFFS,	/* e */
290 	FS_BSDFFS,	/* f */
291 	FS_BSDFFS,	/* g */
292 	FS_BSDFFS,	/* h */
293 };
294 
295 /*
296  * Given a UniOS/ISI disk label, set lp to a BSD disk label.
297  * Returns NULL on success, else an error string.
298  *
299  * The BSD label is cleared out before this is called.
300  */
301 static const char *
disklabel_om_to_bsd(char * cp,struct disklabel * lp)302 disklabel_om_to_bsd(char *cp, struct disklabel *lp)
303 {
304 	struct sun_disklabel *sl;
305 	struct partition *npp;
306 	struct sun_dkpart *spp;
307 	int i, secpercyl;
308 	u_short cksum, *sp1, *sp2;
309 
310 	sl = (struct sun_disklabel *)cp;
311 
312 	/* Verify the XOR check. */
313 	sp1 = (u_short *)sl;
314 	sp2 = (u_short *)(sl + 1);
315 	cksum = 0;
316 	while (sp1 < sp2)
317 		cksum ^= *sp1++;
318 	if (cksum != 0)
319 		return ("UniOS disk label, bad checksum");
320 
321 	memset((void *)lp, 0, sizeof(struct disklabel));
322 	/* Format conversion. */
323 	lp->d_magic = DISKMAGIC;
324 	lp->d_magic2 = DISKMAGIC;
325 	memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname));
326 
327 	lp->d_type	 = DKTYPE_SCSI;
328 	lp->d_secsize	 = 512;
329 	lp->d_nsectors   = sl->sl_nsectors;
330 	lp->d_ntracks    = sl->sl_ntracks;
331 	lp->d_ncylinders = sl->sl_ncylinders;
332 
333 	secpercyl = sl->sl_nsectors * sl->sl_ntracks;
334 	lp->d_secpercyl  = secpercyl;
335 	lp->d_secperunit = secpercyl * sl->sl_ncylinders;
336 
337 	lp->d_sparespercyl = 0;				/* no way to know */
338 	lp->d_acylinders   = sl->sl_acylinders;
339 	lp->d_rpm          = sl->sl_rpm;		/* UniOS - (empty) */
340 	lp->d_interleave   = sl->sl_interleave;		/* UniOS - ndisk */
341 
342 	if (sl->sl_rpm == 0) {
343 		/* UniOS label has blkoffset, not cyloffset */
344 		secpercyl = 1;
345 	}
346 
347 	lp->d_npartitions = 8;
348 	/* These are as defined in <ufs/ffs/fs.h> */
349 	lp->d_bbsize = 8192;				/* XXX */
350 	lp->d_sbsize = 8192;				/* XXX */
351 	for (i = 0; i < 8; i++) {
352 		spp = &sl->sl_part[i];
353 		npp = &lp->d_partitions[i];
354 		npp->p_offset = spp->sdkp_cyloffset * secpercyl;
355 		npp->p_size = spp->sdkp_nsectors;
356 		if (npp->p_size == 0)
357 			npp->p_fstype = FS_UNUSED;
358 		else {
359 			/* Partition has non-zero size.  Set type, etc. */
360 			npp->p_fstype = sun_fstypes[i];
361 
362 			/*
363 			 * The sun label does not store the FFS fields,
364 			 * so just set them with default values here.
365 			 * XXX: This keeps newfs from trying to rewrite
366 			 * XXX: the disk label in the most common case.
367 			 * XXX: (Should remove that code from newfs...)
368 			 */
369 			if (npp->p_fstype == FS_BSDFFS) {
370 				npp->p_fsize = 1024;
371 				npp->p_frag = 8;
372 				npp->p_cpg = 16;
373 			}
374 		}
375 	}
376 
377 	/*
378 	 * XXX BandAid XXX
379 	 * UniOS rootfs sits on part c which don't begin at sect 0,
380 	 * and impossible to mount.  Thus, make it usable as part b.
381 	 */
382 	if (sl->sl_rpm == 0 && lp->d_partitions[2].p_offset != 0) {
383 		lp->d_partitions[1] = lp->d_partitions[2];
384 		lp->d_partitions[1].p_fstype = FS_BSDFFS;
385 	}
386 
387 	lp->d_checksum = dkcksum(lp);
388 
389 	return (NULL);
390 }
391 
392 /*
393  * Given a BSD disk label, update the UniOS disklabel
394  * pointed to by cp with the new info.  Note that the
395  * UniOS disklabel may have other info we need to keep.
396  * Returns zero or error code.
397  */
398 static int
disklabel_bsd_to_om(struct disklabel * lp,char * cp)399 disklabel_bsd_to_om(struct disklabel *lp, char *cp)
400 {
401 	struct sun_disklabel *sl;
402 	struct partition *npp;
403 	struct sun_dkpart *spp;
404 	int i;
405 	u_short cksum, *sp1, *sp2;
406 
407 	if (lp->d_secsize != 512)
408 		return (EINVAL);
409 
410 	sl = (struct sun_disklabel *)cp;
411 
412 	/* Format conversion. */
413 	memcpy(sl->sl_text, lp->d_packname, sizeof(lp->d_packname));
414 	sl->sl_rpm = 0;					/* UniOS */
415 #if 0 /* leave as was */
416 	sl->sl_pcyl = lp->d_ncylinders + lp->d_acylinders;	/* XXX */
417 	sl->sl_sparespercyl = lp->d_sparespercyl;
418 #endif
419 	sl->sl_interleave   = lp->d_interleave;
420 	sl->sl_ncylinders   = lp->d_ncylinders;
421 	sl->sl_acylinders   = lp->d_acylinders;
422 	sl->sl_ntracks      = lp->d_ntracks;
423 	sl->sl_nsectors     = lp->d_nsectors;
424 
425 	for (i = 0; i < 8; i++) {
426 		spp = &sl->sl_part[i];
427 		npp = &lp->d_partitions[i];
428 
429 		spp->sdkp_cyloffset = npp->p_offset;	/* UniOS */
430 		spp->sdkp_nsectors = npp->p_size;
431 	}
432 	sl->sl_magic = SUN_DKMAGIC;
433 
434 	/* Correct the XOR check. */
435 	sp1 = (u_short *)sl;
436 	sp2 = (u_short *)(sl + 1);
437 	sl->sl_cksum = cksum = 0;
438 	while (sp1 < sp2)
439 		cksum ^= *sp1++;
440 	sl->sl_cksum = cksum;
441 
442 	return (0);
443 }
444