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