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