Deleted Added
full compact
biosdisk.c (39724) biosdisk.c (39896)
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
1/*-
2 * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 9 unchanged lines hidden (view full) ---

18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $Id: biosdisk.c,v 1.7 1998/09/28 20:07:39 peter Exp $
26 * $Id: biosdisk.c,v 1.8 1998/09/28 20:08:34 peter Exp $
27 */
28
29/*
30 * BIOS disk device handling.
31 *
32 * Ideas and algorithms from:
33 *
34 * - NetBSD libi386/biosdisk.c
35 * - FreeBSD biosboot/disk.c
36 *
37 * XXX Todo: add bad144 support.
38 */
39
40#include <stand.h>
41
42#include <sys/disklabel.h>
43#include <sys/diskslice.h>
27 */
28
29/*
30 * BIOS disk device handling.
31 *
32 * Ideas and algorithms from:
33 *
34 * - NetBSD libi386/biosdisk.c
35 * - FreeBSD biosboot/disk.c
36 *
37 * XXX Todo: add bad144 support.
38 */
39
40#include <stand.h>
41
42#include <sys/disklabel.h>
43#include <sys/diskslice.h>
44#include <sys/reboot.h>
44
45#include <bootstrap.h>
46#include <btxv86.h>
47#include "libi386.h"
48
49#define BIOSDISK_SECSIZE 512
50#define BUFSIZE (1 * BIOSDISK_SECSIZE)
51#define MAXBDDEV MAXDEV
52
45
46#include <bootstrap.h>
47#include <btxv86.h>
48#include "libi386.h"
49
50#define BIOSDISK_SECSIZE 512
51#define BUFSIZE (1 * BIOSDISK_SECSIZE)
52#define MAXBDDEV MAXDEV
53
54#define DT_ATAPI 0x10 /* disk type for ATAPI floppies */
55#define WDMAJOR 0 /* major numbers for devices we frontend for */
56#define WFDMAJOR 1
57#define FDMAJOR 2
58#define DAMAJOR 4
59
53#ifdef DISK_DEBUG
54# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args)
55#else
56# define DEBUG(fmt, args...)
57#endif
58
59
60struct open_disk {

--- 4 unchanged lines hidden (view full) ---

65 int od_sec;
66 int od_boff; /* block offset from beginning of BIOS disk */
67 int od_flags;
68#define BD_MODEMASK 0x3
69#define BD_MODEINT13 0x0
70#define BD_MODEEDD1 0x1
71#define BD_MODEEDD3 0x2
72#define BD_FLOPPY (1<<2)
60#ifdef DISK_DEBUG
61# define DEBUG(fmt, args...) printf("%s: " fmt "\n" , __FUNCTION__ , ## args)
62#else
63# define DEBUG(fmt, args...)
64#endif
65
66
67struct open_disk {

--- 4 unchanged lines hidden (view full) ---

72 int od_sec;
73 int od_boff; /* block offset from beginning of BIOS disk */
74 int od_flags;
75#define BD_MODEMASK 0x3
76#define BD_MODEINT13 0x0
77#define BD_MODEEDD1 0x1
78#define BD_MODEEDD3 0x2
79#define BD_FLOPPY (1<<2)
73 u_char od_buf[BUFSIZE]; /* transfer buffer (do we want/need this?) */
80 struct disklabel od_disklabel;
81 struct dos_partition od_parttab;
82#define BD_LABELOK (1<<3)
83#define BD_PARTTABOK (1<<4)
74};
75
84};
85
86/*
87 * List of BIOS devices, translation from disk unit number to
88 * BIOS unit number.
89 */
90static struct bdinfo
91{
92 int bd_unit; /* BIOS unit number */
93 int bd_flags;
94 int bd_type; /* BIOS 'drive type' (floppy only) */
95} bdinfo [MAXBDDEV];
96static int nbdinfo = 0;
97
76static int bd_getgeom(struct open_disk *od);
77static int bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest);
78
98static int bd_getgeom(struct open_disk *od);
99static int bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest);
100
79static int bd_edd3probe(int unit);
80static int bd_edd1probe(int unit);
81static int bd_int13probe(int unit);
101static int bd_int13probe(struct bdinfo *bd);
82
83static int bd_init(void);
84static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize);
85static int bd_open(struct open_file *f, void *vdev);
86static int bd_close(struct open_file *f);
87
88struct devsw biosdisk = {
89 "disk",
90 DEVT_DISK,
91 bd_init,
92 bd_strategy,
93 bd_open,
94 bd_close,
95 noioctl
96};
97
102
103static int bd_init(void);
104static int bd_strategy(void *devdata, int flag, daddr_t dblk, size_t size, void *buf, size_t *rsize);
105static int bd_open(struct open_file *f, void *vdev);
106static int bd_close(struct open_file *f);
107
108struct devsw biosdisk = {
109 "disk",
110 DEVT_DISK,
111 bd_init,
112 bd_strategy,
113 bd_open,
114 bd_close,
115 noioctl
116};
117
118static int bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev);
119static void bd_closedisk(struct open_disk *od);
120
98/*
121/*
99 * List of BIOS devices, translation from disk unit number to
100 * BIOS unit number.
122 * Translate between BIOS device numbers and our private unit numbers.
101 */
123 */
102static struct
124int
125bd_bios2unit(int biosdev)
103{
126{
104 int bd_unit; /* BIOS unit number */
105 int bd_flags;
106} bdinfo [MAXBDDEV];
107static int nbdinfo = 0;
127 int i;
128
129 for (i = 0; i < nbdinfo; i++)
130 if (bdinfo[i].bd_unit == biosdev)
131 return(i);
132 return(-1);
133}
108
134
135int
136bd_unit2bios(int unit)
137{
138 if ((unit >= 0) && (unit < nbdinfo))
139 return(bdinfo[unit].bd_unit);
140 return(-1);
141}
142
109/*
110 * Quiz the BIOS for disk devices, save a little info about them.
111 *
112 * XXX should we be consulting the BIOS equipment list, specifically
113 * the value at 0x475?
114 */
115static int
116bd_init(void)
117{
118 int base, unit;
119
120 /* sequence 0, 0x80 */
121 for (base = 0; base <= 0x80; base += 0x80) {
122 for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
143/*
144 * Quiz the BIOS for disk devices, save a little info about them.
145 *
146 * XXX should we be consulting the BIOS equipment list, specifically
147 * the value at 0x475?
148 */
149static int
150bd_init(void)
151{
152 int base, unit;
153
154 /* sequence 0, 0x80 */
155 for (base = 0; base <= 0x80; base += 0x80) {
156 for (unit = base; (nbdinfo < MAXBDDEV); unit++) {
123 bdinfo[nbdinfo].bd_unit = -1;
157 bdinfo[nbdinfo].bd_unit = unit;
124 bdinfo[nbdinfo].bd_flags = (unit < 0x80) ? BD_FLOPPY : 0;
158 bdinfo[nbdinfo].bd_flags = (unit < 0x80) ? BD_FLOPPY : 0;
125
126 if (bd_edd3probe(unit)) {
127 bdinfo[nbdinfo].bd_flags |= BD_MODEEDD3;
128 } else if (bd_edd1probe(unit)) {
129 bdinfo[nbdinfo].bd_flags |= BD_MODEEDD1;
130 } else if (bd_int13probe(unit)) {
131 bdinfo[nbdinfo].bd_flags |= BD_MODEINT13;
132 } else {
159
160 /* XXX add EDD probes */
161 if (!bd_int13probe(&bdinfo[nbdinfo]))
133 break;
162 break;
134 }
163
135 /* XXX we need "disk aliases" to make this simpler */
136 printf("BIOS drive %c: is disk%d\n",
137 (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo);
138 bdinfo[nbdinfo].bd_unit = unit;
139 nbdinfo++;
140 }
141 }
142 return(0);
143}
144
164 /* XXX we need "disk aliases" to make this simpler */
165 printf("BIOS drive %c: is disk%d\n",
166 (unit < 0x80) ? ('A' + unit) : ('C' + unit - 0x80), nbdinfo);
167 bdinfo[nbdinfo].bd_unit = unit;
168 nbdinfo++;
169 }
170 }
171 return(0);
172}
173
145/*
146 * Try to detect a device supported by an Enhanced Disk Drive 3.0-compliant BIOS
147 */
148static int
149bd_edd3probe(int unit)
150{
151 return(0); /* XXX not implemented yet */
152}
153
154/*
155 * Try to detect a device supported by an Enhanced Disk Drive 1.1-compliant BIOS
156 */
157static int
158bd_edd1probe(int unit)
159{
160 return(0); /* XXX not implemented yet */
161}
162
163/*
164 * Try to detect a device supported by the legacy int13 BIOS
165 */
166
167static int
174/*
175 * Try to detect a device supported by the legacy int13 BIOS
176 */
177
178static int
168bd_int13probe(int unit)
179bd_int13probe(struct bdinfo *bd)
169{
180{
181
170 v86.ctl = V86_FLAGS;
171 v86.addr = 0x13;
172 v86.eax = 0x800;
182 v86.ctl = V86_FLAGS;
183 v86.addr = 0x13;
184 v86.eax = 0x800;
173 v86.edx = unit;
185 v86.edx = bd->bd_unit;
174 v86int();
175
186 v86int();
187
176 if (!(v86.efl & 0x1) && /* carry clear */
177 ((v86.edx & 0xff) > (unit & 0x7f))) /* unit # OK */
188 if (!(v86.efl & 0x1) && /* carry clear */
189 ((v86.edx & 0xff) > (bd->bd_unit & 0x7f))) { /* unit # OK */
190 bd->bd_flags |= BD_MODEINT13;
191 bd->bd_type = v86.ebx & 0xff;
178 return(1);
192 return(1);
193 }
179 return(0);
180}
181
182/*
183 * Attempt to open the disk described by (dev) for use by (f).
184 *
185 * Note that the philosophy here is "give them exactly what
186 * they ask for". This is necessary because being too "smart"
187 * about what the user might want leads to complications.
188 * (eg. given no slice or partition value, with a disk that is
189 * sliced - are they after the first BSD slice, or the DOS
190 * slice before it?)
191 */
192static int
193bd_open(struct open_file *f, void *vdev)
194{
195 struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
194 return(0);
195}
196
197/*
198 * Attempt to open the disk described by (dev) for use by (f).
199 *
200 * Note that the philosophy here is "give them exactly what
201 * they ask for". This is necessary because being too "smart"
202 * about what the user might want leads to complications.
203 * (eg. given no slice or partition value, with a disk that is
204 * sliced - are they after the first BSD slice, or the DOS
205 * slice before it?)
206 */
207static int
208bd_open(struct open_file *f, void *vdev)
209{
210 struct i386_devdesc *dev = (struct i386_devdesc *)vdev;
196 struct dos_partition *dptr;
197 struct open_disk *od;
211 struct open_disk *od;
212 int error;
213
214 if ((error = bd_opendisk(&od, dev)))
215 return(error);
216
217 /*
218 * Save our context
219 */
220 ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od;
221 DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff);
222 return(0);
223}
224
225static int
226bd_opendisk(struct open_disk **odp, struct i386_devdesc *dev)
227{
228 struct dos_partition *dptr;
198 struct disklabel *lp;
229 struct disklabel *lp;
230 struct open_disk *od;
199 int sector, slice, i;
200 int error;
231 int sector, slice, i;
232 int error;
233 u_char buf[BUFSIZE];
201
202 if (dev->d_kind.biosdisk.unit >= nbdinfo) {
203 DEBUG("attempt to open nonexistent disk");
204 return(ENXIO);
205 }
206
207 od = (struct open_disk *)malloc(sizeof(struct open_disk));
208 if (!od) {

--- 22 unchanged lines hidden (view full) ---

231 * Following calculations attempt to determine the correct value
232 * for d->od_boff by looking for the slice and partition specified,
233 * or searching for reasonable defaults.
234 */
235
236 /*
237 * Find the slice in the DOS slice table.
238 */
234
235 if (dev->d_kind.biosdisk.unit >= nbdinfo) {
236 DEBUG("attempt to open nonexistent disk");
237 return(ENXIO);
238 }
239
240 od = (struct open_disk *)malloc(sizeof(struct open_disk));
241 if (!od) {

--- 22 unchanged lines hidden (view full) ---

264 * Following calculations attempt to determine the correct value
265 * for d->od_boff by looking for the slice and partition specified,
266 * or searching for reasonable defaults.
267 */
268
269 /*
270 * Find the slice in the DOS slice table.
271 */
239 if (bd_read(od, 0, 1, od->od_buf)) {
272 if (bd_read(od, 0, 1, buf)) {
240 DEBUG("error reading MBR");
241 error = EIO;
242 goto out;
243 }
244
245 /*
246 * Check the slice table magic.
247 */
273 DEBUG("error reading MBR");
274 error = EIO;
275 goto out;
276 }
277
278 /*
279 * Check the slice table magic.
280 */
248 if ((od->od_buf[0x1fe] != 0x55) || (od->od_buf[0x1ff] != 0xaa)) {
281 if ((buf[0x1fe] != 0x55) || (buf[0x1ff] != 0xaa)) {
249 /* If a slice number was explicitly supplied, this is an error */
250 if (dev->d_kind.biosdisk.slice > 0) {
251 DEBUG("no slice table/MBR (no magic)");
252 error = ENOENT;
253 goto out;
254 }
255 sector = 0;
256 goto unsliced; /* may be a floppy */
257 }
282 /* If a slice number was explicitly supplied, this is an error */
283 if (dev->d_kind.biosdisk.slice > 0) {
284 DEBUG("no slice table/MBR (no magic)");
285 error = ENOENT;
286 goto out;
287 }
288 sector = 0;
289 goto unsliced; /* may be a floppy */
290 }
258 dptr = (struct dos_partition *) & od->od_buf[DOSPARTOFF];
291 bcopy(buf + DOSPARTOFF, &od->od_parttab, sizeof(struct dos_partition));
292 dptr = &od->od_parttab;
293 od->od_flags |= BD_PARTTABOK;
259
260 /*
261 * XXX No support here for 'extended' slices
262 */
263 if (dev->d_kind.biosdisk.slice <= 0) {
264 /*
265 * Search for the first FreeBSD slice; this also works on "unsliced"
266 * disks, as they contain a "historically bogus" MBR.

--- 27 unchanged lines hidden (view full) ---

294 *
295 * XXX we might want to check the label checksum.
296 */
297 if (dev->d_kind.biosdisk.partition < 0) {
298 od->od_boff = sector; /* no partition, must be after the slice */
299 DEBUG("opening raw slice");
300 } else {
301
294
295 /*
296 * XXX No support here for 'extended' slices
297 */
298 if (dev->d_kind.biosdisk.slice <= 0) {
299 /*
300 * Search for the first FreeBSD slice; this also works on "unsliced"
301 * disks, as they contain a "historically bogus" MBR.

--- 27 unchanged lines hidden (view full) ---

329 *
330 * XXX we might want to check the label checksum.
331 */
332 if (dev->d_kind.biosdisk.partition < 0) {
333 od->od_boff = sector; /* no partition, must be after the slice */
334 DEBUG("opening raw slice");
335 } else {
336
302 if (bd_read(od, sector + LABELSECTOR, 1, od->od_buf)) {
337 if (bd_read(od, sector + LABELSECTOR, 1, buf)) {
303 DEBUG("error reading disklabel");
304 error = EIO;
305 goto out;
306 }
338 DEBUG("error reading disklabel");
339 error = EIO;
340 goto out;
341 }
307 lp = (struct disklabel *) (od->od_buf + LABELOFFSET);
342 DEBUG("copy %d bytes of label from %p to %p", sizeof(struct disklabel), buf + LABELOFFSET, &od->od_disklabel);
343 bcopy(buf + LABELOFFSET, &od->od_disklabel, sizeof(struct disklabel));
344 lp = &od->od_disklabel;
345 od->od_flags |= BD_LABELOK;
308
309 if (lp->d_magic != DISKMAGIC) {
310 DEBUG("no disklabel");
311 error = ENOENT;
312 goto out;
313 }
314 if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) {
315 DEBUG("partition '%c' exceeds partitions in table (a-'%c')",

--- 5 unchanged lines hidden (view full) ---

321
322 /* Complain if the partition type is wrong */
323 if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) &&
324 !(od->od_flags & BD_FLOPPY)) /* Floppies often have bogus fstype */
325 DEBUG("warning, partition marked as unused");
326
327 od->od_boff = lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset;
328 }
346
347 if (lp->d_magic != DISKMAGIC) {
348 DEBUG("no disklabel");
349 error = ENOENT;
350 goto out;
351 }
352 if (dev->d_kind.biosdisk.partition >= lp->d_npartitions) {
353 DEBUG("partition '%c' exceeds partitions in table (a-'%c')",

--- 5 unchanged lines hidden (view full) ---

359
360 /* Complain if the partition type is wrong */
361 if ((lp->d_partitions[dev->d_kind.biosdisk.partition].p_fstype == FS_UNUSED) &&
362 !(od->od_flags & BD_FLOPPY)) /* Floppies often have bogus fstype */
363 DEBUG("warning, partition marked as unused");
364
365 od->od_boff = lp->d_partitions[dev->d_kind.biosdisk.partition].p_offset;
366 }
329 /*
330 * Save our context
331 */
332 ((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data = od;
333 DEBUG("open_disk %p, partition at 0x%x", od, od->od_boff);
334
367
335 out:
368 out:
336 if (error)
369 if (error) {
337 free(od);
370 free(od);
371 } else {
372 *odp = od; /* return the open disk */
373 }
338 return(error);
339}
340
374 return(error);
375}
376
377
341static int
342bd_close(struct open_file *f)
343{
344 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data);
345
378static int
379bd_close(struct open_file *f)
380{
381 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)(f->f_devdata))->d_kind.biosdisk.data);
382
383 bd_closedisk(od);
384 return(0);
385}
386
387static void
388bd_closedisk(struct open_disk *od)
389{
346 DEBUG("open_disk %p", od);
347#if 0
348 /* XXX is this required? (especially if disk already open...) */
349 if (od->od_flags & BD_FLOPPY)
350 delay(3000000);
351#endif
352 free(od);
390 DEBUG("open_disk %p", od);
391#if 0
392 /* XXX is this required? (especially if disk already open...) */
393 if (od->od_flags & BD_FLOPPY)
394 delay(3000000);
395#endif
396 free(od);
353 return(0);
354}
355
356static int
357bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
358{
359 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
360 int blks;
361#ifdef BD_SUPPORT_FRAGS

--- 154 unchanged lines hidden (view full) ---

516 /* convert max head # -> # of heads */
517 od->od_hds = ((v86.edx & 0xff00) >> 8) + 1;
518 od->od_sec = v86.ecx & 0x3f;
519
520
521 DEBUG("unit 0x%x geometry %d/%d/%d", od->od_unit, od->od_cyl, od->od_hds, od->od_sec);
522 return(0);
523}
397}
398
399static int
400bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t *rsize)
401{
402 struct open_disk *od = (struct open_disk *)(((struct i386_devdesc *)devdata)->d_kind.biosdisk.data);
403 int blks;
404#ifdef BD_SUPPORT_FRAGS

--- 154 unchanged lines hidden (view full) ---

559 /* convert max head # -> # of heads */
560 od->od_hds = ((v86.edx & 0xff00) >> 8) + 1;
561 od->od_sec = v86.ecx & 0x3f;
562
563
564 DEBUG("unit 0x%x geometry %d/%d/%d", od->od_unit, od->od_cyl, od->od_hds, od->od_sec);
565 return(0);
566}
567
568/*
569 * Return a suitable dev_t value for (dev)
570 */
571int
572bd_getdev(struct i386_devdesc *dev)
573{
574 struct open_disk *od;
575 int biosdev;
576 int major;
577
578 biosdev = bd_unit2bios(dev->d_kind.biosdisk.unit);
579 if (biosdev == -1) /* not a BIOS device */
580 return(-1);
581 if (bd_opendisk(&od, dev) != 0) /* oops, not a viable device */
582 return(-1);
583
584 if (biosdev < 0x80) {
585 /* floppy (or emulated floppy) or ATAPI device */
586 if (bdinfo[dev->d_kind.biosdisk.unit].bd_type == DT_ATAPI) {
587 /* is an ATAPI disk */
588 major = WFDMAJOR;
589 } else {
590 /* is a floppy disk */
591 major = FDMAJOR;
592 }
593 } else {
594 /* harddisk */
595 if ((od->od_flags & BD_LABELOK) && (od->od_disklabel.d_type == DTYPE_SCSI)) {
596 /* label OK, disk labelled as SCSI */
597 major = DAMAJOR;
598 } else {
599 /* assume an IDE disk */
600 major = WDMAJOR;
601 }
602 }
603 return(MAKEBOOTDEV(major,
604 (dev->d_kind.biosdisk.slice + 1) >> 4, /* XXX slices may be wrong here */
605 (dev->d_kind.biosdisk.slice + 1) & 0xf,
606 biosdev & 0x7f, /* XXX allow/compute shift for da when wd present */
607 dev->d_kind.biosdisk.partition));
608}