1 /* $NetBSD: biosdisk.c,v 1.3 1997/03/22 01:41:34 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * Matthias Drochner. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Matthias Drochner. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 /* 36 * raw BIOS disk device for libsa. needs lowlevel parts from bios_disk.S and 37 * biosdisk_ll.c partly from netbsd:sys/arch/i386/boot/disk.c no bad144 38 * handling! 39 */ 40 41 /* 42 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 43 * 44 * Mach Operating System 45 * Copyright (c) 1992, 1991 Carnegie Mellon University 46 * All Rights Reserved. 47 * 48 * Permission to use, copy, modify and distribute this software and its 49 * documentation is hereby granted, provided that both the copyright 50 * notice and this permission notice appear in all copies of the 51 * software, derivative works or modified versions, and any portions 52 * thereof, and that both notices appear in supporting documentation. 53 * 54 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 55 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 56 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 57 * 58 * Carnegie Mellon requests users of this software to return to 59 * 60 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 61 * School of Computer Science 62 * Carnegie Mellon University 63 * Pittsburgh PA 15213-3890 64 * 65 * any improvements or extensions that they make and grant Carnegie Mellon 66 * the rights to redistribute these changes. 67 */ 68 69 #include <sys/types.h> 70 #include <sys/disklabel.h> 71 72 #include <lib/libsa/stand.h> 73 #include <lib/libsa/saerrno.h> 74 75 #include "libi386.h" 76 #include "biosdisk_ll.h" 77 /* XXX don't include biosdisk.h for now - vararg prototype */ 78 79 #define BUFSIZE (1 * BIOSDISK_SECSIZE) 80 81 struct biosdisk { 82 struct biosdisk_ll ll; 83 #ifdef COMPAT_OLDBOOT 84 int disktype; 85 #endif 86 int boff; 87 char buf[BUFSIZE]; 88 }; 89 90 int 91 biosdiskstrategy(devdata, flag, dblk, size, buf, rsize) 92 void *devdata; 93 int flag; 94 daddr_t dblk; 95 size_t size; 96 void *buf; 97 size_t *rsize; 98 { 99 struct biosdisk *d; 100 int blks, frag; 101 102 if (flag != F_READ) 103 return (EROFS); 104 105 d = (struct biosdisk *) devdata; 106 107 dblk += d->boff; 108 109 blks = size / BIOSDISK_SECSIZE; 110 if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { 111 if (rsize) 112 *rsize = 0; 113 return (EIO); 114 } 115 /* do we really need this? */ 116 frag = size % BIOSDISK_SECSIZE; 117 if (frag) { 118 if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { 119 if (rsize) 120 *rsize = blks * BIOSDISK_SECSIZE; 121 return (EIO); 122 } 123 bcopy(d->buf, buf + blks * BIOSDISK_SECSIZE, frag); 124 } 125 if (rsize) 126 *rsize = size; 127 return (0); 128 } 129 130 #ifdef COMPAT_OLDBOOT 131 int 132 biosdisk_gettype(f) 133 struct open_file *f; 134 { 135 struct biosdisk *d = f->f_devdata; 136 return (d->disktype); 137 } 138 #endif 139 140 int 141 biosdiskopen(f, biosdev, partition) 142 struct open_file *f; 143 int biosdev; 144 unsigned int partition; 145 { 146 struct biosdisk *d; 147 struct dos_partition *dptr; 148 int sector; 149 int error = 0, i; 150 #ifndef NO_DISKLABEL 151 struct disklabel *lp; 152 #endif 153 154 d = (struct biosdisk *) alloc(sizeof(struct biosdisk)); 155 if (!d) { 156 #ifdef DEBUG 157 printf("biosdiskopen: no memory\n"); 158 #endif 159 return (ENOMEM); 160 } 161 d->ll.dev = biosdev; 162 if (set_geometry(&d->ll)) { 163 #ifdef DISK_DEBUG 164 printf("no geometry information\n"); 165 #endif 166 error = ENXIO; 167 goto out; 168 } 169 /* 170 * find NetBSD Partition in DOS partition table XXX check magic??? 171 */ 172 if (readsects(&d->ll, 0, 1, d->buf, 0)) { 173 #ifdef DISK_DEBUG 174 printf("error reading mbr\n"); 175 #endif 176 error = EIO; 177 goto out; 178 } 179 dptr = (struct dos_partition *) & d->buf[DOSPARTOFF]; 180 sector = -1; 181 for (i = 0; i < NDOSPART; i++, dptr++) 182 if (dptr->dp_typ == DOSPTYP_NETBSD) { 183 sector = dptr->dp_start; 184 break; 185 } 186 if (sector == -1) { 187 /* 188 * One of two things: 189 * 1. no MBR 190 * 2. no NetBSD partition in MBR 191 * 192 * We simply default to "start of disk" in this case and 193 * press on. 194 */ 195 sector = 0; 196 } 197 #ifdef NO_DISKLABEL 198 d->boff = sector; 199 #else 200 /* find partition in NetBSD disklabel */ 201 if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { 202 #ifdef DISK_DEBUG 203 printf("Error reading disklabel\n"); 204 #endif 205 error = EIO; 206 goto out; 207 } 208 lp = (struct disklabel *) (d->buf + LABELOFFSET); 209 if (lp->d_magic != DISKMAGIC) { 210 #ifdef DISK_DEBUG 211 printf("warning: no disklabel\n"); 212 #endif 213 d->boff = sector; 214 } else if (partition >= lp->d_npartitions || 215 lp->d_partitions[partition].p_fstype == FS_UNUSED) { 216 #ifdef DISK_DEBUG 217 printf("illegal partition\n"); 218 #endif 219 error = EPART; 220 goto out; 221 } else { 222 d->boff = lp->d_partitions[partition].p_offset; 223 #ifdef COMPAT_OLDBOOT 224 d->disktype = lp->d_type; 225 #endif 226 } 227 #endif /* NO_DISKLABEL */ 228 229 #ifdef DISK_DEBUG 230 printf("partition @%d\n", d->boff); 231 #endif 232 233 f->f_devdata = d; 234 out: 235 if (error) 236 free(d, sizeof(struct biosdisk)); 237 return (error); 238 } 239 240 int 241 biosdiskclose(f) 242 struct open_file *f; 243 { 244 struct biosdisk *d = f->f_devdata; 245 246 if (!(d->ll.dev & 0x80))/* let the floppy drive go off */ 247 delay(3000000); /* 2s is enough on all PCs I found */ 248 249 free(d, sizeof(struct biosdisk)); 250 f->f_devdata = NULL; 251 return (0); 252 } 253 254 int 255 biosdiskioctl(f, cmd, arg) 256 struct open_file *f; 257 u_long cmd; 258 void *arg; 259 { 260 return EIO; 261 } 262