1 /* $NetBSD: biosdisk.c,v 1.4 1997/06/13 13:36:04 drochner 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. 37 * needs lowlevel parts from bios_disk.S and biosdisk_ll.c 38 * partly from netbsd:sys/arch/i386/boot/disk.c 39 * no bad144 handling! 40 */ 41 42 /* 43 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 44 * 45 * Mach Operating System 46 * Copyright (c) 1992, 1991 Carnegie Mellon University 47 * All Rights Reserved. 48 * 49 * Permission to use, copy, modify and distribute this software and its 50 * documentation is hereby granted, provided that both the copyright 51 * notice and this permission notice appear in all copies of the 52 * software, derivative works or modified versions, and any portions 53 * thereof, and that both notices appear in supporting documentation. 54 * 55 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 56 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 57 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 58 * 59 * Carnegie Mellon requests users of this software to return to 60 * 61 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 62 * School of Computer Science 63 * Carnegie Mellon University 64 * Pittsburgh PA 15213-3890 65 * 66 * any improvements or extensions that they make and grant Carnegie Mellon 67 * the rights to redistribute these changes. 68 */ 69 70 #include <sys/types.h> 71 #include <sys/disklabel.h> 72 73 #include <lib/libsa/stand.h> 74 #include <lib/libsa/saerrno.h> 75 76 #include "libi386.h" 77 #include "biosdisk_ll.h" 78 /* XXX don't include biosdisk.h for now - vararg prototype */ 79 80 #define BUFSIZE (1 * BIOSDISK_SECSIZE) 81 82 struct biosdisk { 83 struct biosdisk_ll ll; 84 #ifdef COMPAT_OLDBOOT 85 int disktype; 86 #endif 87 int boff; 88 char buf[BUFSIZE]; 89 }; 90 91 int 92 biosdiskstrategy(devdata, flag, dblk, size, buf, rsize) 93 void *devdata; 94 int flag; 95 daddr_t dblk; 96 size_t size; 97 void *buf; 98 size_t *rsize; 99 { 100 struct biosdisk *d; 101 int blks, frag; 102 103 if (flag != F_READ) 104 return (EROFS); 105 106 d = (struct biosdisk *) devdata; 107 108 dblk += d->boff; 109 110 blks = size / BIOSDISK_SECSIZE; 111 if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { 112 if (rsize) 113 *rsize = 0; 114 return (EIO); 115 } 116 /* do we really need this? */ 117 frag = size % BIOSDISK_SECSIZE; 118 if (frag) { 119 if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { 120 if (rsize) 121 *rsize = blks * BIOSDISK_SECSIZE; 122 return (EIO); 123 } 124 bcopy(d->buf, buf + blks * BIOSDISK_SECSIZE, frag); 125 } 126 if (rsize) 127 *rsize = size; 128 return (0); 129 } 130 131 #ifdef COMPAT_OLDBOOT 132 int 133 biosdisk_gettype(f) 134 struct open_file *f; 135 { 136 struct biosdisk *d = f->f_devdata; 137 return (d->disktype); 138 } 139 #endif 140 141 int 142 biosdiskopen(f, biosdev, partition) 143 struct open_file *f; 144 int biosdev; 145 unsigned int partition; 146 { 147 struct biosdisk *d; 148 struct dos_partition *dptr; 149 int sector; 150 int error = 0, i; 151 #ifndef NO_DISKLABEL 152 struct disklabel *lp; 153 #endif 154 155 d = (struct biosdisk *) alloc(sizeof(struct biosdisk)); 156 if (!d) { 157 #ifdef DEBUG 158 printf("biosdiskopen: no memory\n"); 159 #endif 160 return (ENOMEM); 161 } 162 d->ll.dev = biosdev; 163 if (set_geometry(&d->ll)) { 164 #ifdef DISK_DEBUG 165 printf("no geometry information\n"); 166 #endif 167 error = ENXIO; 168 goto out; 169 } 170 /* 171 * find NetBSD Partition in DOS partition table XXX check magic??? 172 */ 173 if (readsects(&d->ll, 0, 1, d->buf, 0)) { 174 #ifdef DISK_DEBUG 175 printf("error reading mbr\n"); 176 #endif 177 error = EIO; 178 goto out; 179 } 180 dptr = (struct dos_partition *) & d->buf[DOSPARTOFF]; 181 sector = -1; 182 for (i = 0; i < NDOSPART; i++, dptr++) 183 if (dptr->dp_typ == DOSPTYP_NETBSD) { 184 sector = dptr->dp_start; 185 break; 186 } 187 if (sector == -1) { 188 /* 189 * One of two things: 190 * 1. no MBR 191 * 2. no NetBSD partition in MBR 192 * 193 * We simply default to "start of disk" in this case and 194 * press on. 195 */ 196 sector = 0; 197 } 198 #ifdef NO_DISKLABEL 199 d->boff = sector; 200 #else 201 /* find partition in NetBSD disklabel */ 202 if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { 203 #ifdef DISK_DEBUG 204 printf("Error reading disklabel\n"); 205 #endif 206 error = EIO; 207 goto out; 208 } 209 lp = (struct disklabel *) (d->buf + LABELOFFSET); 210 if (lp->d_magic != DISKMAGIC) { 211 #ifdef DISK_DEBUG 212 printf("warning: no disklabel\n"); 213 #endif 214 d->boff = sector; 215 } else if (partition >= lp->d_npartitions || 216 lp->d_partitions[partition].p_fstype == FS_UNUSED) { 217 #ifdef DISK_DEBUG 218 printf("illegal partition\n"); 219 #endif 220 error = EPART; 221 goto out; 222 } else { 223 d->boff = lp->d_partitions[partition].p_offset; 224 #ifdef COMPAT_OLDBOOT 225 d->disktype = lp->d_type; 226 #endif 227 } 228 #endif /* NO_DISKLABEL */ 229 230 #ifdef DISK_DEBUG 231 printf("partition @%d\n", d->boff); 232 #endif 233 234 f->f_devdata = d; 235 out: 236 if (error) 237 free(d, sizeof(struct biosdisk)); 238 return (error); 239 } 240 241 int 242 biosdiskclose(f) 243 struct open_file *f; 244 { 245 struct biosdisk *d = f->f_devdata; 246 247 if (!(d->ll.dev & 0x80))/* let the floppy drive go off */ 248 delay(3000000); /* 2s is enough on all PCs I found */ 249 250 free(d, sizeof(struct biosdisk)); 251 f->f_devdata = NULL; 252 return (0); 253 } 254 255 int 256 biosdiskioctl(f, cmd, arg) 257 struct open_file *f; 258 u_long cmd; 259 void *arg; 260 { 261 return EIO; 262 } 263