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