4 * Copyright (c) 1996, 1998
5 * Matthias Drochner. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * raw BIOS disk device for libsa.
31 * needs lowlevel parts from bios_disk.S and biosdisk_ll.c
32 * partly from netbsd:sys/arch/i386/boot/disk.c
35 * A lot of this must match sys/kern/subr_disk_mbr.c
39 * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
41 * Mach Operating System
42 * Copyright (c) 1992, 1991 Carnegie Mellon University
43 * All Rights Reserved.
45 * Permission to use, copy, modify and distribute this software and its
46 * documentation is hereby granted, provided that both the copyright
47 * notice and this permission notice appear in all copies of the
48 * software, derivative works or modified versions, and any portions
49 * thereof, and that both notices appear in supporting documentation.
51 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
52 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
53 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
55 * Carnegie Mellon requests users of this software to return to
57 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
58 * School of Computer Science
59 * Carnegie Mellon University
60 * Pittsburgh PA 15213-3890
62 * any improvements or extensions that they make and grant Carnegie Mellon
63 * the rights to redistribute these changes.
66 #include <sys/types.h>
67 #include <sys/disklabel.h>
69 #include <lib/libsa/stand.h>
70 #include <lib/libsa/saerrno.h>
71 #include <lib/libsa/loadfile.h>
73 #include <machine/stdarg.h>
74 #include <machine/disklabel.h>
77 #include "biosdisk_ll.h"
81 #define BUFSIZE (1 * BIOSDISK_SECSIZE)
89 static struct btinfo_bootdisk bi_disk
;
91 #define RF_PROTECTED_SECTORS 64 /* XXX refer to <.../rf_optnames.h> */
93 static struct biosdisk
*
94 alloc_biosdisk(int dev
)
98 d
= (struct biosdisk
*)ALLOC(sizeof(*d
));
102 memset(d
, 0, sizeof(*d
));
109 check_label(struct biosdisk
*d
, int sector
)
111 struct disklabel
*lp
;
113 /* find partition in NetBSD disklabel */
114 if (readsects(d
->dev
, sector
+ LABELSECTOR
, d
->buf
, 1)) {
116 printf("Error reading disklabel\n");
121 lp
= (struct disklabel
*)(d
->buf
+ LABELOFFSET
);
122 if (lp
->d_magic
!= DISKMAGIC
|| dkcksum(lp
)) {
124 printf("warning: no disklabel\n");
134 read_label(struct biosdisk
*d
)
136 struct disklabel dflt_lbl
;
137 struct mbr_partition mbr
[MBR_PART_COUNT
];
142 int ext_base
, this_ext
, next_ext
;
143 #ifdef COMPAT_386BSD_MBRPART
144 int sector_386bsd
= -1;
147 memset(&dflt_lbl
, 0, sizeof dflt_lbl
);
148 dflt_lbl
.d_npartitions
= 8;
153 * find NetBSD Partition in DOS partition table
159 this_ext
= ext_base
+ next_ext
;
161 if (readsects(d
->dev
, this_ext
, d
->buf
, 1)) {
163 printf("error reading MBR sector %d\n", this_ext
);
167 memcpy(&mbr
, ((struct mbr_sector
*)d
->buf
)->mbr_parts
, sizeof(mbr
));
168 /* Look for NetBSD partition ID */
169 for (i
= 0; i
< MBR_PART_COUNT
; i
++) {
170 typ
= mbr
[i
].mbrp_type
;
173 sector
= this_ext
+ mbr
[i
].mbrp_start
;
174 if (typ
== MBR_PTYPE_NETBSD
) {
175 error
= check_label(d
, sector
);
179 if (MBR_IS_EXTENDED(typ
)) {
180 next_ext
= mbr
[i
].mbrp_start
;
183 #ifdef COMPAT_386BSD_MBRPART
184 if (this_ext
== 0 && typ
== MBR_PTYPE_386BSD
)
185 sector_386bsd
= sector
;
188 if (dflt_lbl
.d_npartitions
>= MAXPARTITIONS
)
190 p
= &dflt_lbl
.d_partitions
[dflt_lbl
.d_npartitions
++];
192 p
= &dflt_lbl
.d_partitions
[i
];
193 p
->p_offset
= sector
;
194 p
->p_size
= mbr
[i
].mbrp_size
;
195 p
->p_fstype
= xlat_mbr_fstype(typ
);
206 #ifdef COMPAT_386BSD_MBRPART
207 if (sector_386bsd
!= -1) {
208 printf("old BSD partition ID!\n");
209 sector
= sector_386bsd
;
216 * 2. no NetBSD partition in MBR
218 * We simply default to "start of disk" in this case and
221 error
= check_label(d
, sector
);
226 * Nothing at start of disk, return info from mbr partitions.
228 /* XXX fill it to make checksum match kernel one */
229 dflt_lbl
.d_checksum
= dkcksum(&dflt_lbl
);
230 memcpy(d
->buf
, &dflt_lbl
, sizeof(dflt_lbl
));
236 * Determine likely partition for possible sector number of dos
240 biosdisk_findptn(int biosdev
, u_int sector
)
244 struct disklabel
*lp
;
246 /* Look for netbsd partition that is the dos boot one */
247 d
= alloc_biosdisk(biosdev
);
251 if (read_label(d
) == 0) {
252 lp
= (struct disklabel
*)(d
->buf
+ LABELOFFSET
);
253 for (partition
= lp
->d_npartitions
; --partition
;){
254 if (lp
->d_partitions
[partition
].p_fstype
== FS_UNUSED
)
256 if (lp
->d_partitions
[partition
].p_offset
== sector
)
261 DEALLOC(d
, sizeof(*d
));
266 biosdisk_open(struct open_file
*f
, ...)
270 struct disklabel
*lp
;
276 dev
= va_arg(ap
, int);
277 d
= alloc_biosdisk(dev
);
283 partition
= va_arg(ap
, int);
284 bi_disk
.biosdev
= d
->dev
;
285 bi_disk
.partition
= partition
;
286 bi_disk
.labelsector
= -1;
288 if (partition
== RAW_PART
)
290 error
= read_label(d
);
298 lp
= (struct disklabel
*)(d
->buf
+ LABELOFFSET
);
299 if (partition
>= lp
->d_npartitions
||
300 lp
->d_partitions
[partition
].p_fstype
== FS_UNUSED
) {
302 printf("illegal partition\n");
307 bi_disk
.labelsector
= d
->boff
+ LABELSECTOR
;
308 bi_disk
.label
.type
= lp
->d_type
;
309 memcpy(bi_disk
.label
.packname
, lp
->d_packname
, 16);
310 bi_disk
.label
.checksum
= lp
->d_checksum
;
312 d
->boff
= lp
->d_partitions
[partition
].p_offset
;
313 if (lp
->d_partitions
[partition
].p_fstype
== FS_RAID
) {
314 d
->boff
+= RF_PROTECTED_SECTORS
;
319 printf("partition @%d\n", d
->boff
);
322 BI_ADD(&bi_disk
, BTINFO_BOOTDISK
, sizeof(bi_disk
));
328 DEALLOC(d
, sizeof(struct biosdisk
));
333 biosdisk_close(struct open_file
*f
)
335 struct biosdisk
*d
= f
->f_devdata
;
337 DEALLOC(d
, sizeof(struct biosdisk
));
344 biosdisk_ioctl(struct open_file
*f
, u_long cmd
, void *arg
)
351 biosdisk_strategy(void *devdata
, int flag
, daddr_t dblk
, size_t size
, void *buf
, size_t *rsize
)
360 d
= (struct biosdisk
*)devdata
;
364 blks
= size
/ BIOSDISK_SECSIZE
;
365 if (blks
&& readsects(d
->dev
, dblk
, buf
, blks
)) {
371 /* do we really need this? */
372 frag
= size
% BIOSDISK_SECSIZE
;
374 if (readsects(d
->dev
, dblk
+ blks
, d
->buf
, 1)) {
376 *rsize
= blks
* BIOSDISK_SECSIZE
;
379 memcpy(buf
+ blks
* BIOSDISK_SECSIZE
, d
->buf
, frag
);