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