1 /* $NetBSD: biosdisk.c,v 1.7 1997/10/13 09:26:29 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 #include <machine/stdarg.h> 76 77 #include "libi386.h" 78 #include "biosdisk_ll.h" 79 #include "biosdisk.h" 80 #include "bootinfo.h" 81 82 #define BUFSIZE (1 * BIOSDISK_SECSIZE) 83 84 struct biosdisk { 85 struct biosdisk_ll ll; 86 #ifdef COMPAT_OLDBOOT 87 int disktype; 88 #endif 89 int boff; 90 char buf[BUFSIZE]; 91 }; 92 93 static struct btinfo_bootdisk bi_disk; 94 95 int 96 biosdiskstrategy(devdata, flag, dblk, size, buf, rsize) 97 void *devdata; 98 int flag; 99 daddr_t dblk; 100 size_t size; 101 void *buf; 102 size_t *rsize; 103 { 104 struct biosdisk *d; 105 int blks, frag; 106 107 if (flag != F_READ) 108 return (EROFS); 109 110 d = (struct biosdisk *) devdata; 111 112 dblk += d->boff; 113 114 blks = size / BIOSDISK_SECSIZE; 115 if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { 116 if (rsize) 117 *rsize = 0; 118 return (EIO); 119 } 120 /* do we really need this? */ 121 frag = size % BIOSDISK_SECSIZE; 122 if (frag) { 123 if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { 124 if (rsize) 125 *rsize = blks * BIOSDISK_SECSIZE; 126 return (EIO); 127 } 128 bcopy(d->buf, buf + blks * BIOSDISK_SECSIZE, frag); 129 } 130 if (rsize) 131 *rsize = size; 132 return (0); 133 } 134 135 #ifdef COMPAT_OLDBOOT 136 int 137 biosdisk_gettype(f) 138 struct open_file *f; 139 { 140 struct biosdisk *d = f->f_devdata; 141 return (d->disktype); 142 } 143 #endif 144 145 int 146 biosdiskopen(struct open_file *f, ...) 147 /* file, biosdev, partition */ 148 { 149 va_list ap; 150 struct biosdisk *d; 151 int partition; 152 #ifndef NO_DISKLABEL 153 struct dos_partition *dptr; 154 int sector, i; 155 struct disklabel *lp; 156 #endif 157 int error = 0; 158 159 d = (struct biosdisk *) alloc(sizeof(struct biosdisk)); 160 if (!d) { 161 #ifdef DEBUG 162 printf("biosdiskopen: no memory\n"); 163 #endif 164 return (ENOMEM); 165 } 166 va_start(ap, f); 167 bi_disk.biosdev = d->ll.dev = va_arg(ap, int); 168 if (set_geometry(&d->ll)) { 169 #ifdef DISK_DEBUG 170 printf("no geometry information\n"); 171 #endif 172 error = ENXIO; 173 goto out; 174 } 175 176 d->boff = 0; 177 bi_disk.labelsector = -1; 178 bi_disk.partition = partition = va_arg(ap, int); 179 180 #ifndef NO_DISKLABEL 181 if (!(d->ll.dev & 0x80) /* floppy */ 182 || partition == RAW_PART) 183 goto nolabel; 184 185 /* 186 * find NetBSD Partition in DOS partition table 187 * XXX check magic??? 188 */ 189 if (readsects(&d->ll, 0, 1, d->buf, 0)) { 190 #ifdef DISK_DEBUG 191 printf("error reading MBR\n"); 192 #endif 193 error = EIO; 194 goto out; 195 } 196 dptr = (struct dos_partition *) & d->buf[DOSPARTOFF]; 197 sector = -1; 198 for (i = 0; i < NDOSPART; i++, dptr++) 199 if (dptr->dp_typ == DOSPTYP_NETBSD) { 200 sector = dptr->dp_start; 201 break; 202 } 203 if (sector == -1) { 204 /* 205 * One of two things: 206 * 1. no MBR 207 * 2. no NetBSD partition in MBR 208 * 209 * We simply default to "start of disk" in this case and 210 * press on. 211 */ 212 sector = 0; 213 } 214 215 /* find partition in NetBSD disklabel */ 216 if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { 217 #ifdef DISK_DEBUG 218 printf("Error reading disklabel\n"); 219 #endif 220 error = EIO; 221 goto out; 222 } 223 lp = (struct disklabel *) (d->buf + LABELOFFSET); 224 if (lp->d_magic != DISKMAGIC) { 225 #ifdef DISK_DEBUG 226 printf("warning: no disklabel\n"); 227 #endif 228 d->boff = sector; 229 } else if (partition >= lp->d_npartitions || 230 lp->d_partitions[partition].p_fstype == FS_UNUSED) { 231 #ifdef DISK_DEBUG 232 printf("illegal partition\n"); 233 #endif 234 error = EPART; 235 goto out; 236 } else { 237 d->boff = lp->d_partitions[partition].p_offset; 238 bi_disk.labelsector = sector + LABELSECTOR; 239 #ifdef COMPAT_OLDBOOT 240 d->disktype = 241 #endif 242 bi_disk.label.type = lp->d_type; 243 bcopy(lp->d_packname, bi_disk.label.packname, 16); 244 bi_disk.label.checksum = lp->d_checksum; 245 } 246 nolabel: 247 #endif /* NO_DISKLABEL */ 248 249 #ifdef DISK_DEBUG 250 printf("partition @%d\n", d->boff); 251 #endif 252 253 BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); 254 255 f->f_devdata = d; 256 out: 257 va_end(ap); 258 if (error) 259 free(d, sizeof(struct biosdisk)); 260 return (error); 261 } 262 263 int 264 biosdiskclose(f) 265 struct open_file *f; 266 { 267 struct biosdisk *d = f->f_devdata; 268 269 if (!(d->ll.dev & 0x80))/* let the floppy drive go off */ 270 delay(3000000); /* 2s is enough on all PCs I found */ 271 272 free(d, sizeof(struct biosdisk)); 273 f->f_devdata = NULL; 274 return (0); 275 } 276 277 int 278 biosdiskioctl(f, cmd, arg) 279 struct open_file *f; 280 u_long cmd; 281 void *arg; 282 { 283 return EIO; 284 } 285