1 /* $OpenBSD: dev.c,v 1.3 2011/03/13 00:13:53 deraadt 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/types.h> 48 #include "libsa.h" 49 #include <sys/disklabel.h> 50 #include <machine/param.h> 51 #include <machine/cpu.h> 52 #include <machine/pmon.h> 53 54 /* 55 * PMON I/O 56 */ 57 58 char pmon_bootdev[1 + 256]; 59 60 struct pmon_iodata { 61 int fd; 62 struct disklabel label; 63 off_t partoff; 64 off_t curpos; 65 }; 66 67 int pmon_getdisklabel(struct pmon_iodata *pi); 68 69 int 70 pmon_iostrategy(void *f, int rw, daddr32_t dblk, size_t size, void *buf, 71 size_t *rsize) 72 { 73 struct pmon_iodata *pi = (struct pmon_iodata *)f; 74 off_t offs, pos; 75 int rc; 76 77 *rsize = 0; 78 if (size == 0) 79 return 0; 80 81 if (rw != F_READ) 82 return EOPNOTSUPP; 83 84 offs = ((daddr64_t)dblk + pi->partoff) * DEV_BSIZE; 85 if (offs != pi->curpos) { 86 pos = pmon_lseek(pi->fd, offs, 0 /* SEEK_SET */); 87 if (pos != offs) 88 return EINVAL; 89 } 90 91 /* note this expects size to fit in 32 bits */ 92 rc = pmon_read(pi->fd, buf, size); 93 if (rc >= 0) { 94 pi->curpos += rc; 95 *rsize = rc; 96 } else 97 *rsize = 0; 98 99 if (rc != size) 100 return EIO; 101 return 0; 102 } 103 104 int 105 pmon_ioopen(struct open_file *f, ...) 106 { 107 struct pmon_iodata *pi; 108 int rc; 109 va_list ap; 110 uint unit, part; 111 112 pi = alloc(sizeof *pi); 113 if (pi == NULL) 114 return ENOMEM; 115 bzero(pi, sizeof *pi); 116 f->f_devdata = pi; 117 118 va_start(ap, f); 119 unit = va_arg(ap, uint); 120 part = va_arg(ap, uint); 121 va_end(ap); 122 123 /* 124 * Open the raw device through PMON. 125 */ 126 127 snprintf(pmon_bootdev, sizeof pmon_bootdev, "/dev/disk/%s%d", 128 f->f_dev->dv_name, unit); 129 rc = pmon_open(pmon_bootdev, 0 /* O_RDONLY */); 130 if (rc < 0) 131 return ENXIO; 132 133 pi->fd = rc; 134 135 /* 136 * Read disklabel. 137 */ 138 139 if (pmon_getdisklabel(pi) != 0) { 140 pmon_ioclose(f); 141 return ENXIO; 142 } 143 144 if (part >= pi->label.d_npartitions) { 145 pmon_ioclose(f); 146 return EPART; 147 } 148 149 pi->partoff = DL_GETPOFFSET(&pi->label.d_partitions[part]); 150 pi->curpos = 0; 151 152 return 0; 153 } 154 155 int 156 pmon_ioclose(struct open_file *f) 157 { 158 struct pmon_iodata *pi; 159 int rc; 160 161 if (f->f_devdata != NULL) { 162 pi = (struct pmon_iodata *)f->f_devdata; 163 rc = pmon_close(pi->fd); 164 free(pi, sizeof *pi); 165 f->f_devdata = NULL; 166 } else 167 rc = 0; 168 169 return rc; 170 } 171 172 /* 173 * Read disk label from the device. 174 */ 175 int 176 pmon_getdisklabel(struct pmon_iodata *pi) 177 { 178 char *msg; 179 int sector; 180 size_t rsize; 181 struct disklabel *lp = &pi->label; 182 char buf[DEV_BSIZE]; 183 184 bzero(lp, sizeof *lp); 185 186 /* 187 * Find OpenBSD Partition in DOS partition table. 188 */ 189 sector = 0; 190 if (pmon_iostrategy(pi, F_READ, DOSBBSECTOR, DEV_BSIZE, buf, &rsize)) 191 return ENXIO; 192 193 if (*(u_int16_t *)&buf[DOSMBR_SIGNATURE_OFF] == DOSMBR_SIGNATURE) { 194 int i; 195 struct dos_partition *dp = (struct dos_partition *)buf; 196 197 /* 198 * Lookup OpenBSD slice. If there is none, go ahead 199 * and try to read the disklabel off sector #0. 200 */ 201 memcpy(dp, &buf[DOSPARTOFF], NDOSPART * sizeof(*dp)); 202 for (i = 0; i < NDOSPART; i++) { 203 if (dp[i].dp_typ == DOSPTYP_OPENBSD) { 204 sector = letoh32(dp[i].dp_start); 205 break; 206 } 207 } 208 } 209 210 if (pmon_iostrategy(pi, F_READ, sector + LABELSECTOR, DEV_BSIZE, 211 buf, &rsize)) 212 return ENXIO; 213 214 if ((msg = getdisklabel(buf + LABELOFFSET, lp))) { 215 printf("getdisklabel: %s\n", msg); 216 return ENXIO; 217 } 218 219 return 0; 220 } 221