xref: /openbsd/sys/arch/loongson/stand/boot/dev.c (revision fc61954a)
1 /*	$OpenBSD: dev.c,v 1.8 2015/10/01 20:28:12 krw Exp $	*/
2 
3 /*
4  * Copyright (c) 2010 Miodrag Vallat.
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 /*-
19  * Copyright (c) 2003 The NetBSD Foundation, Inc.
20  * All rights reserved.
21  *
22  * This code is derived from software contributed to The NetBSD Foundation
23  * by Manuel Bouyer.
24  *
25  * Redistribution and use in source and binary forms, with or without
26  * modification, are permitted provided that the following conditions
27  * are met:
28  * 1. Redistributions of source code must retain the above copyright
29  *    notice, this list of conditions and the following disclaimer.
30  * 2. Redistributions in binary form must reproduce the above copyright
31  *    notice, this list of conditions and the following disclaimer in the
32  *    documentation and/or other materials provided with the distribution.
33  *
34  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44  * POSSIBILITY OF SUCH DAMAGE.
45  */
46 
47 #include <sys/param.h>
48 #include "libsa.h"
49 #include <sys/disklabel.h>
50 #include <machine/cpu.h>
51 #include <machine/pmon.h>
52 
53 /*
54  * PMON I/O
55  */
56 
57 char	pmon_bootdev[1 + 256];
58 
59 struct pmon_iodata {
60 	int			fd;
61 	struct disklabel	label;
62 	off_t			partoff;
63 	off_t			curpos;
64 };
65 
66 int	pmon_getdisklabel(struct pmon_iodata *pi);
67 
68 int
69 pmon_iostrategy(void *f, int rw, daddr32_t dblk, size_t size, void *buf,
70     size_t *rsize)
71 {
72 	struct pmon_iodata *pi = (struct pmon_iodata *)f;
73 	off_t offs, pos;
74 	int rc;
75 
76 	*rsize = 0;
77 	if (size == 0)
78 		return 0;
79 
80 	if (rw != F_READ)
81 		return EOPNOTSUPP;
82 
83 	offs = ((daddr_t)dblk + pi->partoff) * DEV_BSIZE;
84 	if (offs != pi->curpos) {
85 		pos = pmon_lseek(pi->fd, offs, 0 /* SEEK_SET */);
86 		if (pos != offs)
87 			return EINVAL;
88 	}
89 
90 	/* note this expects size to fit in 32 bits */
91 	rc = pmon_read(pi->fd, buf, size);
92 	if (rc >= 0) {
93 		pi->curpos += rc;
94 		*rsize = rc;
95 	} else
96 		*rsize = 0;
97 
98 	if (rc != size)
99 		return EIO;
100 	return 0;
101 }
102 
103 int
104 pmon_ioopen(struct open_file *f, ...)
105 {
106 	struct pmon_iodata *pi;
107 	int rc;
108 	va_list ap;
109 	uint unit, part;
110 
111 	pi = alloc(sizeof *pi);
112 	if (pi == NULL)
113 		return ENOMEM;
114 	bzero(pi, sizeof *pi);
115 	f->f_devdata = pi;
116 
117 	va_start(ap, f);
118 	unit = va_arg(ap, uint);
119 	part = va_arg(ap, uint);
120 	va_end(ap);
121 
122 	/*
123 	 * Open the raw device through PMON.
124 	 */
125 
126 	snprintf(pmon_bootdev, sizeof pmon_bootdev, "/dev/disk/%s%d",
127 	    f->f_dev->dv_name, unit);
128 	rc = pmon_open(pmon_bootdev, 0 /* O_RDONLY */);
129 	if (rc < 0)
130 		return ENXIO;
131 
132 	pi->fd = rc;
133 
134 	/*
135 	 * Read disklabel.
136 	 */
137 
138 	if (pmon_getdisklabel(pi) != 0) {
139 		pmon_ioclose(f);
140 		return ENXIO;
141 	}
142 
143 	if (part >= pi->label.d_npartitions) {
144 		pmon_ioclose(f);
145 		return EPART;
146 	}
147 
148 	pi->partoff = DL_GETPOFFSET(&pi->label.d_partitions[part]);
149 	pi->curpos = 0;
150 
151 	return 0;
152 }
153 
154 int
155 pmon_ioclose(struct open_file *f)
156 {
157 	struct pmon_iodata *pi;
158 	int rc;
159 
160 	if (f->f_devdata != NULL) {
161 		pi = (struct pmon_iodata *)f->f_devdata;
162 		rc = pmon_close(pi->fd);
163 		free(pi, sizeof *pi);
164 		f->f_devdata = NULL;
165 	} else
166 		rc = 0;
167 
168 	return rc;
169 }
170 
171 /*
172  * Read disk label from the device.
173  */
174 int
175 pmon_getdisklabel(struct pmon_iodata *pi)
176 {
177 	char *msg;
178 	int sector;
179 	size_t rsize;
180 	struct disklabel *lp = &pi->label;
181 	char buf[DEV_BSIZE];
182 
183 	bzero(lp, sizeof *lp);
184 
185 	/*
186 	 * Find OpenBSD Partition in DOS partition table.
187 	 */
188 	sector = 0;
189 	if (pmon_iostrategy(pi, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize))
190 		return ENXIO;
191 
192 	if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) {
193 		int i;
194 		struct dos_partition *dp = (struct dos_partition *)buf;
195 
196 		/*
197 		 * Lookup OpenBSD slice. If there is none, go ahead
198 		 * and try to read the disklabel off sector #0.
199 		 */
200 		memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp));
201 		for (i = 0; i < NDOSPART; i++) {
202 			if (dp[i].dp_typ == DOSPTYP_OPENBSD) {
203 				sector = letoh32(dp[i].dp_start);
204 				break;
205 			}
206 		}
207 	}
208 
209 	if (pmon_iostrategy(pi, F_READ, sector + DOS_LABELSECTOR, DEV_BSIZE,
210 				buf, &rsize))
211 		return ENXIO;
212 
213 	if ((msg = getdisklabel(buf + LABELOFFSET, lp))) {
214 		printf("getdisklabel: %s\n", msg);
215 		return ENXIO;
216 	}
217 
218 	return 0;
219 }
220