biosdisk.c revision 1.4 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 (at) 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 (at) 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