xref: /netbsd-src/sys/arch/ews4800mips/ews4800mips/disksubr.c (revision 9337b12fa8130dac15517cd1bf5793461d3f64d5)
1 /*	$NetBSD: disksubr.c,v 1.8 2009/08/02 12:04:28 uch Exp $	*/
2 
3 /*-
4  * Copyright (c) 2004 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by UCHIYAMA Yasushi.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: disksubr.c,v 1.8 2009/08/02 12:04:28 uch Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/disk.h>
38 #include <sys/buf.h>
39 #include <sys/disklabel.h>
40 
41 #include <machine/sector.h>
42 
43 #define	DISKLABEL_DEBUG
44 
45 #ifdef DISKLABEL_DEBUG
46 #define	DPRINTF(fmt, args...)	printf(fmt, ##args)
47 #else
48 #define	DPRINTF(arg...)		((void)0)
49 #endif
50 
51 const char *
readdisklabel(dev_t dev,void (* strategy)(struct buf *),struct disklabel * d,struct cpu_disklabel * ux)52 readdisklabel(dev_t dev, void (*strategy)(struct buf *), struct disklabel *d,
53     struct cpu_disklabel *ux)
54 {
55 	uint8_t buf[DEV_BSIZE];
56 	struct pdinfo_sector *pdinfo = &ux->pdinfo;
57 	struct vtoc_sector *vtoc = &ux->vtoc;
58 	bool disklabel_available = false;
59 	bool vtoc_available = false;
60 	void *rwops;
61 
62 	if ((rwops = sector_init(dev, strategy)) == 0)
63 		return "can't read/write disk";
64 
65 	/* Read VTOC */
66 	if (!pdinfo_sector(rwops, pdinfo) || !pdinfo_sanity(pdinfo)) {
67 		DPRINTF("%s: PDINFO not found.\n", __func__);
68 	} else if (vtoc_sector(rwops, vtoc, pdinfo->logical_sector) &&
69 	    vtoc_sanity(vtoc)) {
70 		vtoc_available = true;
71 
72 		/* Read BSD DISKLABEL (if any) */
73 		sector_read(rwops, buf, LABELSECTOR);
74 		if (disklabel_sanity((struct disklabel *)buf)) {
75 			disklabel_available = true;
76 			memcpy(d, buf, sizeof(struct disklabel));
77 		} else {
78 			DPRINTF("%s: no BSD disklabel.\n", __func__);
79 		}
80 	} else {
81 		DPRINTF("%s: PDINFO found, but VTOC not found.\n", __func__);
82 	}
83 	sector_fini(rwops);
84 
85 	/* If there is no BSD disklabel, convert from VTOC */
86 	if (!disklabel_available) {
87 		if (vtoc_available) {
88 			DPRINTF("%s: creating disklabel from VTOC.\n",
89 			    __func__);
90 		} else {
91 			DPRINTF("%s: no VTOC. creating default disklabel.\n",
92 			    __func__);
93 			vtoc_set_default(ux, d);
94 		}
95 		disklabel_set_default(d);
96 		vtoc_to_disklabel(ux, d);
97 	}
98 
99 	return 0;
100 }
101 
102 int
setdisklabel(struct disklabel * od,struct disklabel * nd,u_long openmask,struct cpu_disklabel * ux)103 setdisklabel(struct disklabel *od, struct disklabel *nd, u_long openmask,
104     struct cpu_disklabel *ux)
105 {
106 
107 	KDASSERT(openmask == 0); /* openmask is obsolete. -uch */
108 
109 	if (!disklabel_sanity(nd))
110 		return EINVAL;
111 
112 	*od = *nd;
113 
114 	return 0;
115 }
116 
117 int
writedisklabel(dev_t dev,void (* strategy)(struct buf *),struct disklabel * d,struct cpu_disklabel * ux)118 writedisklabel(dev_t dev, void (*strategy)(struct buf *), struct disklabel *d,
119     struct cpu_disklabel *ux)
120 {
121 	uint8_t buf[DEV_BSIZE];
122 	int err = 0;
123 	void *rwops;
124 
125 	if (!disklabel_sanity(d))
126 		return EINVAL;
127 
128 	/* 1. Update VTOC */
129 	disklabel_to_vtoc(ux, d);
130 	DPRINTF("%s: logical_sector=%d\n", __func__, ux->pdinfo.logical_sector);
131 
132 	if ((rwops = sector_init(dev, strategy)) == 0)
133 		return ENOMEM;
134 	pdinfo_sanity(&ux->pdinfo);
135 	vtoc_sanity(&ux->vtoc);
136 
137 	/* 2. Write VTOC to bootblock */
138 	sector_write(rwops, (void *)&ux->pdinfo, PDINFO_SECTOR);
139 	sector_write(rwops, (void *)&ux->vtoc,
140 	    ux->pdinfo.logical_sector + VTOC_SECTOR);
141 
142 	/* 3. Write disklabel to LABELSECTOR */
143 	memset(buf, 0, sizeof buf);
144 	memcpy(buf, d, sizeof *d);
145 	if (!sector_write(rwops, buf, LABELSECTOR)) {
146 		DPRINTF("%s: failed to write disklabel.\n", __func__);
147 		err = EIO;
148 	}
149 	sector_fini(rwops);
150 
151 	return err;
152 }
153