| @@ -1,1653 +1,1655 @@ | | | @@ -1,1653 +1,1655 @@ |
1 | /* $NetBSD: biosdisk.c,v 1.56 2021/12/28 00:34:30 simonb Exp $ */ | | 1 | /* $NetBSD: biosdisk.c,v 1.57 2021/12/28 00:37:16 simonb Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996, 1998 | | 4 | * Copyright (c) 1996, 1998 |
5 | * Matthias Drochner. All rights reserved. | | 5 | * Matthias Drochner. All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 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 | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 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 | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 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 | | 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. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | * | | 26 | * |
27 | */ | | 27 | */ |
28 | | | 28 | |
29 | /* | | 29 | /* |
30 | * raw BIOS disk device for libsa. | | 30 | * raw BIOS disk device for libsa. |
31 | * needs lowlevel parts from bios_disk.S and biosdisk_ll.c | | 31 | * needs lowlevel parts from bios_disk.S and biosdisk_ll.c |
32 | * partly from netbsd:sys/arch/i386/boot/disk.c | | 32 | * partly from netbsd:sys/arch/i386/boot/disk.c |
33 | * no bad144 handling! | | 33 | * no bad144 handling! |
34 | * | | 34 | * |
35 | * A lot of this must match sys/kern/subr_disk_mbr.c | | 35 | * A lot of this must match sys/kern/subr_disk_mbr.c |
36 | */ | | 36 | */ |
37 | | | 37 | |
38 | /* | | 38 | /* |
39 | * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 | | 39 | * Ported to boot 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 |
40 | * | | 40 | * |
41 | * Mach Operating System | | 41 | * Mach Operating System |
42 | * Copyright (c) 1992, 1991 Carnegie Mellon University | | 42 | * Copyright (c) 1992, 1991 Carnegie Mellon University |
43 | * All Rights Reserved. | | 43 | * All Rights Reserved. |
44 | * | | 44 | * |
45 | * Permission to use, copy, modify and distribute this software and its | | 45 | * Permission to use, copy, modify and distribute this software and its |
46 | * documentation is hereby granted, provided that both the copyright | | 46 | * documentation is hereby granted, provided that both the copyright |
47 | * notice and this permission notice appear in all copies of the | | 47 | * notice and this permission notice appear in all copies of the |
48 | * software, derivative works or modified versions, and any portions | | 48 | * software, derivative works or modified versions, and any portions |
49 | * thereof, and that both notices appear in supporting documentation. | | 49 | * thereof, and that both notices appear in supporting documentation. |
50 | * | | 50 | * |
51 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" | | 51 | * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" |
52 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR | | 52 | * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR |
53 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. | | 53 | * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. |
54 | * | | 54 | * |
55 | * Carnegie Mellon requests users of this software to return to | | 55 | * Carnegie Mellon requests users of this software to return to |
56 | * | | 56 | * |
57 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU | | 57 | * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU |
58 | * School of Computer Science | | 58 | * School of Computer Science |
59 | * Carnegie Mellon University | | 59 | * Carnegie Mellon University |
60 | * Pittsburgh PA 15213-3890 | | 60 | * Pittsburgh PA 15213-3890 |
61 | * | | 61 | * |
62 | * any improvements or extensions that they make and grant Carnegie Mellon | | 62 | * any improvements or extensions that they make and grant Carnegie Mellon |
63 | * the rights to redistribute these changes. | | 63 | * the rights to redistribute these changes. |
64 | */ | | 64 | */ |
65 | | | 65 | |
66 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 66 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
67 | #define FSTYPENAMES | | 67 | #define FSTYPENAMES |
68 | #endif | | 68 | #endif |
69 | | | 69 | |
70 | #include <lib/libkern/libkern.h> | | 70 | #include <lib/libkern/libkern.h> |
71 | #include <lib/libsa/stand.h> | | 71 | #include <lib/libsa/stand.h> |
72 | | | 72 | |
73 | #include <sys/types.h> | | 73 | #include <sys/types.h> |
74 | #include <sys/md5.h> | | 74 | #include <sys/md5.h> |
75 | #include <sys/param.h> | | 75 | #include <sys/param.h> |
76 | #include <sys/disklabel.h> | | 76 | #include <sys/disklabel.h> |
77 | #include <sys/disklabel_gpt.h> | | 77 | #include <sys/disklabel_gpt.h> |
78 | #include <sys/uuid.h> | | 78 | #include <sys/uuid.h> |
79 | | | 79 | |
80 | #include <fs/cd9660/iso.h> | | 80 | #include <fs/cd9660/iso.h> |
81 | #include <fs/unicode.h> | | 81 | #include <fs/unicode.h> |
82 | | | 82 | |
83 | #include <lib/libsa/saerrno.h> | | 83 | #include <lib/libsa/saerrno.h> |
84 | #include <machine/cpu.h> | | 84 | #include <machine/cpu.h> |
85 | | | 85 | |
86 | #include "libi386.h" | | 86 | #include "libi386.h" |
87 | #include "biosdisk_ll.h" | | 87 | #include "biosdisk_ll.h" |
88 | #include "biosdisk.h" | | 88 | #include "biosdisk.h" |
89 | #ifdef _STANDALONE | | 89 | #ifdef _STANDALONE |
90 | #include "bootinfo.h" | | 90 | #include "bootinfo.h" |
91 | #endif | | 91 | #endif |
92 | | | 92 | |
93 | #ifndef NO_GPT | | 93 | #ifndef NO_GPT |
94 | #define MAXDEVNAME 39 /* "NAME=" + 34 char part_name */ | | 94 | #define MAXDEVNAME 39 /* "NAME=" + 34 char part_name */ |
95 | #else | | 95 | #else |
96 | #define MAXDEVNAME 16 | | 96 | #define MAXDEVNAME 16 |
97 | #endif | | 97 | #endif |
98 | | | 98 | |
99 | #ifndef BIOSDISK_BUFSIZE | | 99 | #ifndef BIOSDISK_BUFSIZE |
100 | #define BIOSDISK_BUFSIZE 2048 /* must be large enough for a CD sector */ | | 100 | #define BIOSDISK_BUFSIZE 2048 /* must be large enough for a CD sector */ |
101 | #endif | | 101 | #endif |
102 | | | 102 | |
103 | #define BIOSDISKNPART 26 | | 103 | #define BIOSDISKNPART 26 |
104 | | | 104 | |
105 | struct biosdisk { | | 105 | struct biosdisk { |
106 | struct biosdisk_ll ll; | | 106 | struct biosdisk_ll ll; |
107 | daddr_t boff; | | 107 | daddr_t boff; |
108 | char buf[BIOSDISK_BUFSIZE]; | | 108 | char buf[BIOSDISK_BUFSIZE]; |
109 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 109 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
110 | struct biosdisk_partition part[BIOSDISKNPART]; | | 110 | struct biosdisk_partition part[BIOSDISKNPART]; |
111 | #endif | | 111 | #endif |
112 | }; | | 112 | }; |
113 | | | 113 | |
114 | #include <dev/raidframe/raidframevar.h> | | 114 | #include <dev/raidframe/raidframevar.h> |
115 | #define RF_COMPONENT_INFO_OFFSET 16384 /* from sys/dev/raidframe/rf_netbsdkintf.c */ | | 115 | #define RF_COMPONENT_INFO_OFFSET 16384 /* from sys/dev/raidframe/rf_netbsdkintf.c */ |
116 | #define RF_COMPONENT_LABEL_VERSION 2 /* from <dev/raidframe/rf_raid.h> */ | | 116 | #define RF_COMPONENT_LABEL_VERSION 2 /* from <dev/raidframe/rf_raid.h> */ |
117 | | | 117 | |
118 | #define RAIDFRAME_NDEV 16 /* abitrary limit to 15 raidframe devices */ | | 118 | #define RAIDFRAME_NDEV 16 /* abitrary limit to 15 raidframe devices */ |
119 | struct raidframe { | | 119 | struct raidframe { |
120 | int last_unit; | | 120 | int last_unit; |
121 | int serial; | | 121 | int serial; |
122 | int biosdev; | | 122 | int biosdev; |
123 | int parent_part; | | 123 | int parent_part; |
124 | #ifndef NO_GPT | | 124 | #ifndef NO_GPT |
125 | char parent_name[MAXDEVNAME + 1]; | | 125 | char parent_name[MAXDEVNAME + 1]; |
126 | #endif | | 126 | #endif |
127 | daddr_t offset; | | 127 | daddr_t offset; |
128 | daddr_t size; | | 128 | daddr_t size; |
129 | }; | | 129 | }; |
130 | | | 130 | |
131 | | | 131 | |
132 | #ifndef NO_GPT | | 132 | #ifndef NO_GPT |
133 | const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; | | 133 | const struct uuid GET_nbsd_raid = GPT_ENT_TYPE_NETBSD_RAIDFRAME; |
134 | const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; | | 134 | const struct uuid GET_nbsd_ffs = GPT_ENT_TYPE_NETBSD_FFS; |
135 | const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; | | 135 | const struct uuid GET_nbsd_lfs = GPT_ENT_TYPE_NETBSD_LFS; |
136 | const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; | | 136 | const struct uuid GET_nbsd_swap = GPT_ENT_TYPE_NETBSD_SWAP; |
137 | const struct uuid GET_nbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD; | | 137 | const struct uuid GET_nbsd_ccd = GPT_ENT_TYPE_NETBSD_CCD; |
138 | const struct uuid GET_nbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD; | | 138 | const struct uuid GET_nbsd_cgd = GPT_ENT_TYPE_NETBSD_CGD; |
139 | | | 139 | |
140 | const struct uuid GET_efi = GPT_ENT_TYPE_EFI; | | 140 | const struct uuid GET_efi = GPT_ENT_TYPE_EFI; |
141 | const struct uuid GET_mbr = GPT_ENT_TYPE_MBR; | | 141 | const struct uuid GET_mbr = GPT_ENT_TYPE_MBR; |
142 | const struct uuid GET_fbsd = GPT_ENT_TYPE_FREEBSD; | | 142 | const struct uuid GET_fbsd = GPT_ENT_TYPE_FREEBSD; |
143 | const struct uuid GET_fbsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; | | 143 | const struct uuid GET_fbsd_swap = GPT_ENT_TYPE_FREEBSD_SWAP; |
144 | const struct uuid GET_fbsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; | | 144 | const struct uuid GET_fbsd_ufs = GPT_ENT_TYPE_FREEBSD_UFS; |
145 | const struct uuid GET_fbsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; | | 145 | const struct uuid GET_fbsd_vinum = GPT_ENT_TYPE_FREEBSD_VINUM; |
146 | const struct uuid GET_fbsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; | | 146 | const struct uuid GET_fbsd_zfs = GPT_ENT_TYPE_FREEBSD_ZFS; |
147 | const struct uuid GET_ms_rsvd = GPT_ENT_TYPE_MS_RESERVED; | | 147 | const struct uuid GET_ms_rsvd = GPT_ENT_TYPE_MS_RESERVED; |
148 | const struct uuid GET_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; | | 148 | const struct uuid GET_ms_basic_data = GPT_ENT_TYPE_MS_BASIC_DATA; |
149 | const struct uuid GET_ms_ldm_metadata = GPT_ENT_TYPE_MS_LDM_METADATA; | | 149 | const struct uuid GET_ms_ldm_metadata = GPT_ENT_TYPE_MS_LDM_METADATA; |
150 | const struct uuid GET_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA; | | 150 | const struct uuid GET_ms_ldm_data = GPT_ENT_TYPE_MS_LDM_DATA; |
151 | const struct uuid GET_linux_data = GPT_ENT_TYPE_LINUX_DATA; | | 151 | const struct uuid GET_linux_data = GPT_ENT_TYPE_LINUX_DATA; |
152 | const struct uuid GET_linux_raid = GPT_ENT_TYPE_LINUX_RAID; | | 152 | const struct uuid GET_linux_raid = GPT_ENT_TYPE_LINUX_RAID; |
153 | const struct uuid GET_linux_swap = GPT_ENT_TYPE_LINUX_SWAP; | | 153 | const struct uuid GET_linux_swap = GPT_ENT_TYPE_LINUX_SWAP; |
154 | const struct uuid GET_linux_lvm = GPT_ENT_TYPE_LINUX_LVM; | | 154 | const struct uuid GET_linux_lvm = GPT_ENT_TYPE_LINUX_LVM; |
155 | const struct uuid GET_apple_hfs = GPT_ENT_TYPE_APPLE_HFS; | | 155 | const struct uuid GET_apple_hfs = GPT_ENT_TYPE_APPLE_HFS; |
156 | const struct uuid GET_apple_ufs = GPT_ENT_TYPE_APPLE_UFS; | | 156 | const struct uuid GET_apple_ufs = GPT_ENT_TYPE_APPLE_UFS; |
157 | const struct uuid GET_bios = GPT_ENT_TYPE_BIOS; | | 157 | const struct uuid GET_bios = GPT_ENT_TYPE_BIOS; |
158 | | | 158 | |
159 | const struct gpt_part gpt_parts[] = { | | 159 | const struct gpt_part gpt_parts[] = { |
160 | { &GET_nbsd_raid, "NetBSD RAID" }, | | 160 | { &GET_nbsd_raid, "NetBSD RAID" }, |
161 | { &GET_nbsd_ffs, "NetBSD FFS" }, | | 161 | { &GET_nbsd_ffs, "NetBSD FFS" }, |
162 | { &GET_nbsd_lfs, "NetBSD LFS" }, | | 162 | { &GET_nbsd_lfs, "NetBSD LFS" }, |
163 | { &GET_nbsd_swap, "NetBSD Swap" }, | | 163 | { &GET_nbsd_swap, "NetBSD Swap" }, |
164 | { &GET_nbsd_ccd, "NetBSD ccd" }, | | 164 | { &GET_nbsd_ccd, "NetBSD ccd" }, |
165 | { &GET_nbsd_cgd, "NetBSD cgd" }, | | 165 | { &GET_nbsd_cgd, "NetBSD cgd" }, |
166 | { &GET_efi, "EFI System" }, | | 166 | { &GET_efi, "EFI System" }, |
167 | { &GET_mbr, "MBR" }, | | 167 | { &GET_mbr, "MBR" }, |
168 | { &GET_fbsd, "FreeBSD" }, | | 168 | { &GET_fbsd, "FreeBSD" }, |
169 | { &GET_fbsd_swap, "FreeBSD Swap" }, | | 169 | { &GET_fbsd_swap, "FreeBSD Swap" }, |
170 | { &GET_fbsd_ufs, "FreeBSD UFS" }, | | 170 | { &GET_fbsd_ufs, "FreeBSD UFS" }, |
171 | { &GET_fbsd_vinum, "FreeBSD Vinum" }, | | 171 | { &GET_fbsd_vinum, "FreeBSD Vinum" }, |
172 | { &GET_fbsd_zfs, "FreeBSD ZFS" }, | | 172 | { &GET_fbsd_zfs, "FreeBSD ZFS" }, |
173 | { &GET_ms_rsvd, "Microsoft Reserved" }, | | 173 | { &GET_ms_rsvd, "Microsoft Reserved" }, |
174 | { &GET_ms_basic_data, "Microsoft Basic data" }, | | 174 | { &GET_ms_basic_data, "Microsoft Basic data" }, |
175 | { &GET_ms_ldm_metadata, "Microsoft LDM metadata" }, | | 175 | { &GET_ms_ldm_metadata, "Microsoft LDM metadata" }, |
176 | { &GET_ms_ldm_data, "Microsoft LDM data" }, | | 176 | { &GET_ms_ldm_data, "Microsoft LDM data" }, |
177 | { &GET_linux_data, "Linux data" }, | | 177 | { &GET_linux_data, "Linux data" }, |
178 | { &GET_linux_raid, "Linux RAID" }, | | 178 | { &GET_linux_raid, "Linux RAID" }, |
179 | { &GET_linux_swap, "Linux Swap" }, | | 179 | { &GET_linux_swap, "Linux Swap" }, |
180 | { &GET_linux_lvm, "Linux LVM" }, | | 180 | { &GET_linux_lvm, "Linux LVM" }, |
181 | { &GET_apple_hfs, "Apple HFS" }, | | 181 | { &GET_apple_hfs, "Apple HFS" }, |
182 | { &GET_apple_ufs, "Apple UFS" }, | | 182 | { &GET_apple_ufs, "Apple UFS" }, |
183 | { &GET_bios, "BIOS Boot (GRUB)" }, | | 183 | { &GET_bios, "BIOS Boot (GRUB)" }, |
184 | }; | | 184 | }; |
185 | #endif /* NO_GPT */ | | 185 | #endif /* NO_GPT */ |
186 | | | 186 | |
187 | struct btinfo_bootdisk bi_disk; | | 187 | struct btinfo_bootdisk bi_disk; |
188 | struct btinfo_bootwedge bi_wedge; | | 188 | struct btinfo_bootwedge bi_wedge; |
189 | struct btinfo_rootdevice bi_root; | | 189 | struct btinfo_rootdevice bi_root; |
190 | | | 190 | |
191 | #define MBR_PARTS(buf) ((char *)(buf) + offsetof(struct mbr_sector, mbr_parts)) | | 191 | #define MBR_PARTS(buf) ((char *)(buf) + offsetof(struct mbr_sector, mbr_parts)) |
192 | | | 192 | |
193 | #ifndef devb2cdb | | 193 | #ifndef devb2cdb |
194 | #define devb2cdb(bno) (((bno) * DEV_BSIZE) / ISO_DEFAULT_BLOCK_SIZE) | | 194 | #define devb2cdb(bno) (((bno) * DEV_BSIZE) / ISO_DEFAULT_BLOCK_SIZE) |
195 | #endif | | 195 | #endif |
196 | | | 196 | |
197 | static void | | 197 | static void |
198 | dealloc_biosdisk(struct biosdisk *d) | | 198 | dealloc_biosdisk(struct biosdisk *d) |
199 | { | | 199 | { |
200 | #ifndef NO_GPT | | 200 | #ifndef NO_GPT |
201 | int i; | | 201 | int i; |
202 | | | 202 | |
203 | for (i = 0; i < __arraycount(d->part); i++) { | | 203 | for (i = 0; i < __arraycount(d->part); i++) { |
204 | if (d->part[i].part_name != NULL) | | 204 | if (d->part[i].part_name != NULL) |
205 | dealloc(d->part[i].part_name, BIOSDISK_PART_NAME_LEN); | | 205 | dealloc(d->part[i].part_name, BIOSDISK_PART_NAME_LEN); |
206 | } | | 206 | } |
207 | #endif | | 207 | #endif |
208 | | | 208 | |
209 | dealloc(d, sizeof(*d)); | | 209 | dealloc(d, sizeof(*d)); |
210 | | | 210 | |
211 | return; | | 211 | return; |
212 | } | | 212 | } |
213 | | | 213 | |
214 | static struct biosdisk_partition * | | 214 | static struct biosdisk_partition * |
215 | copy_biosdisk_part(struct biosdisk *d) | | 215 | copy_biosdisk_part(struct biosdisk *d) |
216 | { | | 216 | { |
217 | struct biosdisk_partition *part; | | 217 | struct biosdisk_partition *part; |
218 | | | 218 | |
219 | part = alloc(sizeof(d->part)); | | 219 | part = alloc(sizeof(d->part)); |
220 | if (part == NULL) | | 220 | if (part == NULL) |
221 | goto out; | | 221 | goto out; |
222 | | | 222 | |
223 | memcpy(part, d->part, sizeof(d->part)); | | 223 | memcpy(part, d->part, sizeof(d->part)); |
224 | | | 224 | |
225 | #ifndef NO_GPT | | 225 | #ifndef NO_GPT |
226 | int i; | | 226 | int i; |
227 | | | 227 | |
228 | for (i = 0; i < __arraycount(d->part); i++) { | | 228 | for (i = 0; i < __arraycount(d->part); i++) { |
229 | if (d->part[i].part_name != NULL) { | | 229 | if (d->part[i].part_name != NULL) { |
230 | part[i].part_name = alloc(BIOSDISK_PART_NAME_LEN); | | 230 | part[i].part_name = alloc(BIOSDISK_PART_NAME_LEN); |
231 | memcpy(part[i].part_name, d->part[i].part_name, | | 231 | memcpy(part[i].part_name, d->part[i].part_name, |
232 | BIOSDISK_PART_NAME_LEN); | | 232 | BIOSDISK_PART_NAME_LEN); |
233 | } | | 233 | } |
234 | } | | 234 | } |
235 | #endif | | 235 | #endif |
236 | | | 236 | |
237 | out: | | 237 | out: |
238 | return part; | | 238 | return part; |
239 | } | | 239 | } |
240 | | | 240 | |
241 | int | | 241 | int |
242 | biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, | | 242 | biosdisk_strategy(void *devdata, int flag, daddr_t dblk, size_t size, |
243 | void *buf, size_t *rsize) | | 243 | void *buf, size_t *rsize) |
244 | { | | 244 | { |
245 | struct biosdisk *d; | | 245 | struct biosdisk *d; |
246 | int blks, frag; | | 246 | int blks, frag; |
247 | | | 247 | |
248 | if (flag != F_READ) | | 248 | if (flag != F_READ) |
249 | return EROFS; | | 249 | return EROFS; |
250 | | | 250 | |
251 | d = (struct biosdisk *) devdata; | | 251 | d = (struct biosdisk *) devdata; |
252 | | | 252 | |
253 | if (d->ll.type == BIOSDISK_TYPE_CD) | | 253 | if (d->ll.type == BIOSDISK_TYPE_CD) |
254 | dblk = devb2cdb(dblk); | | 254 | dblk = devb2cdb(dblk); |
255 | | | 255 | |
256 | dblk += d->boff; | | 256 | dblk += d->boff; |
257 | | | 257 | |
258 | blks = size / d->ll.secsize; | | 258 | blks = size / d->ll.secsize; |
259 | if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { | | 259 | if (blks && readsects(&d->ll, dblk, blks, buf, 0)) { |
260 | if (rsize) | | 260 | if (rsize) |
261 | *rsize = 0; | | 261 | *rsize = 0; |
262 | return EIO; | | 262 | return EIO; |
263 | } | | 263 | } |
264 | | | 264 | |
265 | /* needed for CD */ | | 265 | /* needed for CD */ |
266 | frag = size % d->ll.secsize; | | 266 | frag = size % d->ll.secsize; |
267 | if (frag) { | | 267 | if (frag) { |
268 | if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { | | 268 | if (readsects(&d->ll, dblk + blks, 1, d->buf, 0)) { |
269 | if (rsize) | | 269 | if (rsize) |
270 | *rsize = blks * d->ll.secsize; | | 270 | *rsize = blks * d->ll.secsize; |
271 | return EIO; | | 271 | return EIO; |
272 | } | | 272 | } |
273 | memcpy(buf + blks * d->ll.secsize, d->buf, frag); | | 273 | memcpy(buf + blks * d->ll.secsize, d->buf, frag); |
274 | } | | 274 | } |
275 | | | 275 | |
276 | if (rsize) | | 276 | if (rsize) |
277 | *rsize = size; | | 277 | *rsize = size; |
278 | return 0; | | 278 | return 0; |
279 | } | | 279 | } |
280 | | | 280 | |
281 | static struct biosdisk * | | 281 | static struct biosdisk * |
282 | alloc_biosdisk(int biosdev) | | 282 | alloc_biosdisk(int biosdev) |
283 | { | | 283 | { |
284 | struct biosdisk *d; | | 284 | struct biosdisk *d; |
285 | | | 285 | |
286 | d = alloc(sizeof(*d)); | | 286 | d = alloc(sizeof(*d)); |
287 | if (d == NULL) | | 287 | if (d == NULL) |
288 | return NULL; | | 288 | return NULL; |
289 | memset(d, 0, sizeof(*d)); | | 289 | memset(d, 0, sizeof(*d)); |
290 | | | 290 | |
291 | d->ll.dev = biosdev; | | 291 | d->ll.dev = biosdev; |
292 | if (set_geometry(&d->ll, NULL)) { | | 292 | if (set_geometry(&d->ll, NULL)) { |
293 | #ifdef DISK_DEBUG | | 293 | #ifdef DISK_DEBUG |
294 | printf("no geometry information\n"); | | 294 | printf("no geometry information\n"); |
295 | #endif | | 295 | #endif |
296 | dealloc_biosdisk(d); | | 296 | dealloc_biosdisk(d); |
297 | return NULL; | | 297 | return NULL; |
298 | } | | 298 | } |
299 | return d; | | 299 | return d; |
300 | } | | 300 | } |
301 | | | 301 | |
302 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 302 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
303 | static void | | 303 | static void |
304 | md5(void *hash, const void *data, size_t len) | | 304 | md5(void *hash, const void *data, size_t len) |
305 | { | | 305 | { |
306 | MD5_CTX ctx; | | 306 | MD5_CTX ctx; |
307 | | | 307 | |
308 | MD5Init(&ctx); | | 308 | MD5Init(&ctx); |
309 | MD5Update(&ctx, data, len); | | 309 | MD5Update(&ctx, data, len); |
310 | MD5Final(hash, &ctx); | | 310 | MD5Final(hash, &ctx); |
311 | | | 311 | |
312 | return; | | 312 | return; |
313 | } | | 313 | } |
314 | #endif | | 314 | #endif |
315 | | | 315 | |
316 | #ifndef NO_GPT | | 316 | #ifndef NO_GPT |
317 | bool | | 317 | bool |
318 | guid_is_nil(const struct uuid *u) | | 318 | guid_is_nil(const struct uuid *u) |
319 | { | | 319 | { |
320 | static const struct uuid nil = { .time_low = 0 }; | | 320 | static const struct uuid nil = { .time_low = 0 }; |
321 | return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false); | | 321 | return (memcmp(u, &nil, sizeof(*u)) == 0 ? true : false); |
322 | } | | 322 | } |
323 | | | 323 | |
324 | bool | | 324 | bool |
325 | guid_is_equal(const struct uuid *a, const struct uuid *b) | | 325 | guid_is_equal(const struct uuid *a, const struct uuid *b) |
326 | { | | 326 | { |
327 | return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); | | 327 | return (memcmp(a, b, sizeof(*a)) == 0 ? true : false); |
328 | } | | 328 | } |
329 | | | 329 | |
330 | #ifndef NO_GPT | | 330 | #ifndef NO_GPT |
331 | static void | | 331 | static void |
332 | part_name_utf8(const uint16_t *utf16_src, size_t utf16_srclen, | | 332 | part_name_utf8(const uint16_t *utf16_src, size_t utf16_srclen, |
333 | char *utf8_dst, size_t utf8_dstlen) | | 333 | char *utf8_dst, size_t utf8_dstlen) |
334 | { | | 334 | { |
335 | char *c = utf8_dst; | | 335 | char *c = utf8_dst; |
336 | size_t r = utf8_dstlen - 1; | | 336 | size_t r = utf8_dstlen - 1; |
337 | size_t n; | | 337 | size_t n; |
338 | int j; | | 338 | int j; |
339 | | | 339 | |
340 | if (utf8_dst == NULL) | | 340 | if (utf8_dst == NULL) |
341 | return; | | 341 | return; |
342 | | | 342 | |
343 | for (j = 0; j < utf16_srclen && utf16_src[j] != 0x0000; j++) { | | 343 | for (j = 0; j < utf16_srclen && utf16_src[j] != 0x0000; j++) { |
344 | n = wput_utf8(c, r, le16toh(utf16_src[j])); | | 344 | n = wput_utf8(c, r, le16toh(utf16_src[j])); |
345 | if (n == 0) | | 345 | if (n == 0) |
346 | break; | | 346 | break; |
347 | c += n; r -= n; | | 347 | c += n; r -= n; |
348 | } | | 348 | } |
349 | *c = '\0'; | | 349 | *c = '\0'; |
350 | | | 350 | |
351 | return; | | 351 | return; |
352 | } | | 352 | } |
353 | #endif | | 353 | #endif |
354 | | | 354 | |
355 | static int | | 355 | static int |
356 | check_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t sector) | | 356 | check_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t sector) |
357 | { | | 357 | { |
358 | struct gpt_hdr gpth; | | 358 | struct gpt_hdr gpth; |
359 | const struct gpt_ent *ep; | | 359 | const struct gpt_ent *ep; |
360 | const struct uuid *u; | | 360 | const struct uuid *u; |
361 | daddr_t entblk; | | 361 | daddr_t entblk; |
362 | size_t size; | | 362 | size_t size; |
363 | uint32_t crc; | | 363 | uint32_t crc; |
364 | int sectors; | | 364 | int sectors; |
365 | int entries; | | 365 | int entries; |
366 | int entry; | | 366 | int entry; |
367 | int i, j; | | 367 | int i, j; |
368 | | | 368 | |
369 | /* read in gpt_hdr sector */ | | 369 | /* read in gpt_hdr sector */ |
370 | if (readsects(&d->ll, sector, 1, d->buf, 1)) { | | 370 | if (readsects(&d->ll, sector, 1, d->buf, 1)) { |
371 | #ifdef DISK_DEBUG | | 371 | #ifdef DISK_DEBUG |
372 | printf("Error reading GPT header at %"PRId64"\n", sector); | | 372 | printf("Error reading GPT header at %"PRId64"\n", sector); |
373 | #endif | | 373 | #endif |
374 | return EIO; | | 374 | return EIO; |
375 | } | | 375 | } |
376 | | | 376 | |
377 | memcpy(&gpth, d->buf, sizeof(gpth)); | | 377 | memcpy(&gpth, d->buf, sizeof(gpth)); |
378 | | | 378 | |
379 | if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig))) | | 379 | if (memcmp(GPT_HDR_SIG, gpth.hdr_sig, sizeof(gpth.hdr_sig))) |
380 | return -1; | | 380 | return -1; |
381 | | | 381 | |
382 | crc = gpth.hdr_crc_self; | | 382 | crc = gpth.hdr_crc_self; |
383 | gpth.hdr_crc_self = 0; | | 383 | gpth.hdr_crc_self = 0; |
384 | gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE); | | 384 | gpth.hdr_crc_self = crc32(0, (const void *)&gpth, GPT_HDR_SIZE); |
385 | if (gpth.hdr_crc_self != crc) { | | 385 | if (gpth.hdr_crc_self != crc) { |
386 | return -1; | | 386 | return -1; |
387 | } | | 387 | } |
388 | | | 388 | |
389 | if (gpth.hdr_lba_self + rf_offset != sector) | | 389 | if (gpth.hdr_lba_self + rf_offset != sector) |
390 | return -1; | | 390 | return -1; |
391 | | | 391 | |
392 | #ifdef _STANDALONE | | 392 | #ifdef _STANDALONE |
393 | bi_wedge.matchblk = sector; | | 393 | bi_wedge.matchblk = sector; |
394 | bi_wedge.matchnblks = 1; | | 394 | bi_wedge.matchnblks = 1; |
395 | | | 395 | |
396 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); | | 396 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); |
397 | #endif | | 397 | #endif |
398 | | | 398 | |
399 | sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ | | 399 | sectors = sizeof(d->buf)/d->ll.secsize; /* sectors per buffer */ |
400 | entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ | | 400 | entries = sizeof(d->buf)/gpth.hdr_entsz; /* entries per buffer */ |
401 | entblk = gpth.hdr_lba_table + rf_offset; | | 401 | entblk = gpth.hdr_lba_table + rf_offset; |
402 | crc = crc32(0, NULL, 0); | | 402 | crc = crc32(0, NULL, 0); |
403 | | | 403 | |
404 | j = 0; | | 404 | j = 0; |
405 | ep = (const struct gpt_ent *)d->buf; | | 405 | ep = (const struct gpt_ent *)d->buf; |
406 | | | 406 | |
407 | for (entry = 0; entry < gpth.hdr_entries; entry += entries) { | | 407 | for (entry = 0; entry < gpth.hdr_entries; entry += entries) { |
408 | size = MIN(sizeof(d->buf), | | 408 | size = MIN(sizeof(d->buf), |
409 | (gpth.hdr_entries - entry) * gpth.hdr_entsz); | | 409 | (gpth.hdr_entries - entry) * gpth.hdr_entsz); |
410 | entries = size / gpth.hdr_entsz; | | 410 | entries = size / gpth.hdr_entsz; |
411 | sectors = roundup(size, d->ll.secsize) / d->ll.secsize; | | 411 | sectors = roundup(size, d->ll.secsize) / d->ll.secsize; |
412 | if (readsects(&d->ll, entblk, sectors, d->buf, 1)) | | 412 | if (readsects(&d->ll, entblk, sectors, d->buf, 1)) |
413 | return -1; | | 413 | return -1; |
414 | entblk += sectors; | | 414 | entblk += sectors; |
415 | crc = crc32(crc, (const void *)d->buf, size); | | 415 | crc = crc32(crc, (const void *)d->buf, size); |
416 | | | 416 | |
417 | for (i = 0; j < BIOSDISKNPART && i < entries; i++) { | | 417 | for (i = 0; j < BIOSDISKNPART && i < entries; i++) { |
418 | u = (const struct uuid *)ep[i].ent_type; | | 418 | u = (const struct uuid *)ep[i].ent_type; |
419 | if (!guid_is_nil(u)) { | | 419 | if (!guid_is_nil(u)) { |
420 | d->part[j].offset = ep[i].ent_lba_start; | | 420 | d->part[j].offset = ep[i].ent_lba_start; |
421 | d->part[j].size = ep[i].ent_lba_end - | | 421 | d->part[j].size = ep[i].ent_lba_end - |
422 | ep[i].ent_lba_start + 1; | | 422 | ep[i].ent_lba_start + 1; |
423 | if (guid_is_equal(u, &GET_nbsd_ffs)) | | 423 | if (guid_is_equal(u, &GET_nbsd_ffs)) |
424 | d->part[j].fstype = FS_BSDFFS; | | 424 | d->part[j].fstype = FS_BSDFFS; |
425 | else if (guid_is_equal(u, &GET_nbsd_lfs)) | | 425 | else if (guid_is_equal(u, &GET_nbsd_lfs)) |
426 | d->part[j].fstype = FS_BSDLFS; | | 426 | d->part[j].fstype = FS_BSDLFS; |
427 | else if (guid_is_equal(u, &GET_nbsd_raid)) | | 427 | else if (guid_is_equal(u, &GET_nbsd_raid)) |
428 | d->part[j].fstype = FS_RAID; | | 428 | d->part[j].fstype = FS_RAID; |
429 | else if (guid_is_equal(u, &GET_nbsd_swap)) | | 429 | else if (guid_is_equal(u, &GET_nbsd_swap)) |
430 | d->part[j].fstype = FS_SWAP; | | 430 | d->part[j].fstype = FS_SWAP; |
431 | else if (guid_is_equal(u, &GET_nbsd_ccd)) | | 431 | else if (guid_is_equal(u, &GET_nbsd_ccd)) |
432 | d->part[j].fstype = FS_CCD; | | 432 | d->part[j].fstype = FS_CCD; |
433 | else if (guid_is_equal(u, &GET_nbsd_cgd)) | | 433 | else if (guid_is_equal(u, &GET_nbsd_cgd)) |
434 | d->part[j].fstype = FS_CGD; | | 434 | d->part[j].fstype = FS_CGD; |
435 | else | | 435 | else |
436 | d->part[j].fstype = FS_OTHER; | | 436 | d->part[j].fstype = FS_OTHER; |
437 | #ifndef NO_GPT | | 437 | #ifndef NO_GPT |
438 | for (int k = 0; | | 438 | for (int k = 0; |
439 | k < __arraycount(gpt_parts); | | 439 | k < __arraycount(gpt_parts); |
440 | k++) { | | 440 | k++) { |
441 | if (guid_is_equal(u, gpt_parts[k].guid)) | | 441 | if (guid_is_equal(u, gpt_parts[k].guid)) |
442 | d->part[j].guid = &gpt_parts[k]; | | 442 | d->part[j].guid = &gpt_parts[k]; |
443 | } | | 443 | } |
444 | d->part[j].attr = ep[i].ent_attr; | | 444 | d->part[j].attr = ep[i].ent_attr; |
445 | | | 445 | |
446 | d->part[j].part_name = | | 446 | d->part[j].part_name = |
447 | alloc(BIOSDISK_PART_NAME_LEN); | | 447 | alloc(BIOSDISK_PART_NAME_LEN); |
448 | part_name_utf8(ep[i].ent_name, | | 448 | part_name_utf8(ep[i].ent_name, |
449 | sizeof(ep[i].ent_name), | | 449 | sizeof(ep[i].ent_name), |
450 | d->part[j].part_name, | | 450 | d->part[j].part_name, |
451 | BIOSDISK_PART_NAME_LEN); | | 451 | BIOSDISK_PART_NAME_LEN); |
452 | #endif | | 452 | #endif |
453 | j++; | | 453 | j++; |
454 | } | | 454 | } |
455 | } | | 455 | } |
456 | | | 456 | |
457 | } | | 457 | } |
458 | | | 458 | |
459 | if (crc != gpth.hdr_crc_table) { | | 459 | if (crc != gpth.hdr_crc_table) { |
460 | #ifdef DISK_DEBUG | | 460 | #ifdef DISK_DEBUG |
461 | printf("GPT table CRC invalid\n"); | | 461 | printf("GPT table CRC invalid\n"); |
462 | #endif | | 462 | #endif |
463 | return -1; | | 463 | return -1; |
464 | } | | 464 | } |
465 | | | 465 | |
466 | return 0; | | 466 | return 0; |
467 | } | | 467 | } |
468 | | | 468 | |
469 | static int | | 469 | static int |
470 | read_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t rf_size) | | 470 | read_gpt(struct biosdisk *d, daddr_t rf_offset, daddr_t rf_size) |
471 | { | | 471 | { |
472 | struct biosdisk_extinfo ed; | | 472 | struct biosdisk_extinfo ed; |
473 | daddr_t gptsector[2]; | | 473 | daddr_t gptsector[2]; |
474 | int i, error; | | 474 | int i, error; |
475 | | | 475 | |
476 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 476 | if (d->ll.type != BIOSDISK_TYPE_HD) |
477 | /* No GPT on floppy and CD */ | | 477 | /* No GPT on floppy and CD */ |
478 | return -1; | | 478 | return -1; |
479 | | | 479 | |
480 | if (rf_offset && rf_size) { | | 480 | if (rf_offset && rf_size) { |
481 | gptsector[0] = rf_offset + GPT_HDR_BLKNO; | | 481 | gptsector[0] = rf_offset + GPT_HDR_BLKNO; |
482 | gptsector[1] = rf_offset + rf_size - 1; | | 482 | gptsector[1] = rf_offset + rf_size - 1; |
483 | } else { | | 483 | } else { |
484 | gptsector[0] = GPT_HDR_BLKNO; | | 484 | gptsector[0] = GPT_HDR_BLKNO; |
485 | if (set_geometry(&d->ll, &ed) == 0 && | | 485 | if (set_geometry(&d->ll, &ed) == 0 && |
486 | d->ll.flags & BIOSDISK_INT13EXT) { | | 486 | d->ll.flags & BIOSDISK_INT13EXT) { |
487 | gptsector[1] = ed.totsec - 1; | | 487 | gptsector[1] = ed.totsec - 1; |
488 | /* Sanity check values returned from BIOS */ | | 488 | /* Sanity check values returned from BIOS */ |
489 | if (ed.sbytes >= 512 && | | 489 | if (ed.sbytes >= 512 && |
490 | (ed.sbytes & (ed.sbytes - 1)) == 0) | | 490 | (ed.sbytes & (ed.sbytes - 1)) == 0) |
491 | d->ll.secsize = ed.sbytes; | | 491 | d->ll.secsize = ed.sbytes; |
492 | } else { | | 492 | } else { |
493 | #ifdef DISK_DEBUG | | 493 | #ifdef DISK_DEBUG |
494 | printf("Unable to determine extended disk geometry - " | | 494 | printf("Unable to determine extended disk geometry - " |
495 | "using CHS\n"); | | 495 | "using CHS\n"); |
496 | #endif | | 496 | #endif |
497 | /* at least try some other reasonable values then */ | | 497 | /* at least try some other reasonable values then */ |
498 | gptsector[1] = d->ll.chs_sectors - 1; | | 498 | gptsector[1] = d->ll.chs_sectors - 1; |
499 | } | | 499 | } |
500 | } | | 500 | } |
501 | | | 501 | |
502 | for (i = 0; i < __arraycount(gptsector); i++) { | | 502 | for (i = 0; i < __arraycount(gptsector); i++) { |
503 | error = check_gpt(d, rf_offset, gptsector[i]); | | 503 | error = check_gpt(d, rf_offset, gptsector[i]); |
504 | if (error == 0) | | 504 | if (error == 0) |
505 | break; | | 505 | break; |
506 | } | | 506 | } |
507 | | | 507 | |
508 | if (i >= __arraycount(gptsector)) { | | 508 | if (i >= __arraycount(gptsector)) { |
509 | memset(d->part, 0, sizeof(d->part)); | | 509 | memset(d->part, 0, sizeof(d->part)); |
510 | return -1; | | 510 | return -1; |
511 | } | | 511 | } |
512 | | | 512 | |
513 | #ifndef USE_SECONDARY_GPT | | 513 | #ifndef USE_SECONDARY_GPT |
514 | if (i > 0) { | | 514 | if (i > 0) { |
515 | #ifdef DISK_DEBUG | | 515 | #ifdef DISK_DEBUG |
516 | printf("ignoring valid secondary GPT\n"); | | 516 | printf("ignoring valid secondary GPT\n"); |
517 | #endif | | 517 | #endif |
518 | return -1; | | 518 | return -1; |
519 | } | | 519 | } |
520 | #endif | | 520 | #endif |
521 | | | 521 | |
522 | #ifdef DISK_DEBUG | | 522 | #ifdef DISK_DEBUG |
523 | printf("using %s GPT\n", (i == 0) ? "primary" : "secondary"); | | 523 | printf("using %s GPT\n", (i == 0) ? "primary" : "secondary"); |
524 | #endif | | 524 | #endif |
525 | return 0; | | 525 | return 0; |
526 | } | | 526 | } |
527 | #endif /* !NO_GPT */ | | 527 | #endif /* !NO_GPT */ |
528 | | | 528 | |
529 | #ifndef NO_DISKLABEL | | 529 | #ifndef NO_DISKLABEL |
530 | static void | | 530 | static void |
531 | ingest_label(struct biosdisk *d, struct disklabel *lp) | | 531 | ingest_label(struct biosdisk *d, struct disklabel *lp) |
532 | { | | 532 | { |
533 | int part; | | 533 | int part; |
534 | | | 534 | |
535 | memset(d->part, 0, sizeof(d->part)); | | 535 | memset(d->part, 0, sizeof(d->part)); |
536 | | | 536 | |
537 | for (part = 0; part < lp->d_npartitions; part++) { | | 537 | for (part = 0; part < lp->d_npartitions; part++) { |
538 | if (lp->d_partitions[part].p_size == 0) | | 538 | if (lp->d_partitions[part].p_size == 0) |
539 | continue; | | 539 | continue; |
540 | if (lp->d_partitions[part].p_fstype == FS_UNUSED) | | 540 | if (lp->d_partitions[part].p_fstype == FS_UNUSED) |
541 | continue; | | 541 | continue; |
542 | d->part[part].fstype = lp->d_partitions[part].p_fstype; | | 542 | d->part[part].fstype = lp->d_partitions[part].p_fstype; |
543 | d->part[part].offset = lp->d_partitions[part].p_offset; | | 543 | d->part[part].offset = lp->d_partitions[part].p_offset; |
544 | d->part[part].size = lp->d_partitions[part].p_size; | | 544 | d->part[part].size = lp->d_partitions[part].p_size; |
545 | } | | 545 | } |
546 | } | | 546 | } |
547 | | | 547 | |
548 | static int | | 548 | static int |
549 | check_label(struct biosdisk *d, daddr_t sector) | | 549 | check_label(struct biosdisk *d, daddr_t sector) |
550 | { | | 550 | { |
551 | struct disklabel *lp; | | 551 | struct disklabel *lp; |
552 | | | 552 | |
553 | /* find partition in NetBSD disklabel */ | | 553 | /* find partition in NetBSD disklabel */ |
554 | if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { | | 554 | if (readsects(&d->ll, sector + LABELSECTOR, 1, d->buf, 0)) { |
555 | #ifdef DISK_DEBUG | | 555 | #ifdef DISK_DEBUG |
556 | printf("Error reading disklabel\n"); | | 556 | printf("Error reading disklabel\n"); |
557 | #endif | | 557 | #endif |
558 | return EIO; | | 558 | return EIO; |
559 | } | | 559 | } |
560 | lp = (struct disklabel *) (d->buf + LABELOFFSET); | | 560 | lp = (struct disklabel *) (d->buf + LABELOFFSET); |
561 | if (lp->d_magic != DISKMAGIC || dkcksum(lp)) { | | 561 | if (lp->d_magic != DISKMAGIC || dkcksum(lp)) { |
562 | #ifdef DISK_DEBUG | | 562 | #ifdef DISK_DEBUG |
563 | printf("warning: no disklabel in sector %"PRId64"\n", sector); | | 563 | printf("warning: no disklabel in sector %"PRId64"\n", sector); |
564 | #endif | | 564 | #endif |
565 | return -1; | | 565 | return -1; |
566 | } | | 566 | } |
567 | | | 567 | |
568 | ingest_label(d, lp); | | 568 | ingest_label(d, lp); |
569 | | | 569 | |
570 | bi_disk.labelsector = sector + LABELSECTOR; | | 570 | bi_disk.labelsector = sector + LABELSECTOR; |
571 | bi_disk.label.type = lp->d_type; | | 571 | bi_disk.label.type = lp->d_type; |
572 | memcpy(bi_disk.label.packname, lp->d_packname, 16); | | 572 | memcpy(bi_disk.label.packname, lp->d_packname, 16); |
573 | bi_disk.label.checksum = lp->d_checksum; | | 573 | bi_disk.label.checksum = lp->d_checksum; |
574 | | | 574 | |
575 | bi_wedge.matchblk = sector + LABELSECTOR; | | 575 | bi_wedge.matchblk = sector + LABELSECTOR; |
576 | bi_wedge.matchnblks = 1; | | 576 | bi_wedge.matchnblks = 1; |
577 | | | 577 | |
578 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); | | 578 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); |
579 | | | 579 | |
580 | return 0; | | 580 | return 0; |
581 | } | | 581 | } |
582 | | | 582 | |
583 | static int | | 583 | static int |
584 | read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl, | | 584 | read_minix_subp(struct biosdisk *d, struct disklabel* dflt_lbl, |
585 | int this_ext, daddr_t sector) | | 585 | int this_ext, daddr_t sector) |
586 | { | | 586 | { |
587 | struct mbr_partition mbr[MBR_PART_COUNT]; | | 587 | struct mbr_partition mbr[MBR_PART_COUNT]; |
588 | int i; | | 588 | int i; |
589 | int typ; | | 589 | int typ; |
590 | struct partition *p; | | 590 | struct partition *p; |
591 | | | 591 | |
592 | if (readsects(&d->ll, sector, 1, d->buf, 0)) { | | 592 | if (readsects(&d->ll, sector, 1, d->buf, 0)) { |
593 | #ifdef DISK_DEBUG | | 593 | #ifdef DISK_DEBUG |
594 | printf("Error reading MFS sector %"PRId64"\n", sector); | | 594 | printf("Error reading MFS sector %"PRId64"\n", sector); |
595 | #endif | | 595 | #endif |
596 | return EIO; | | 596 | return EIO; |
597 | } | | 597 | } |
598 | if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) { | | 598 | if ((uint8_t)d->buf[510] != 0x55 || (uint8_t)d->buf[511] != 0xAA) { |
599 | return -1; | | 599 | return -1; |
600 | } | | 600 | } |
601 | memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr)); | | 601 | memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr)); |
602 | for (i = 0; i < MBR_PART_COUNT; i++) { | | 602 | for (i = 0; i < MBR_PART_COUNT; i++) { |
603 | typ = mbr[i].mbrp_type; | | 603 | typ = mbr[i].mbrp_type; |
604 | if (typ == 0) | | 604 | if (typ == 0) |
605 | continue; | | 605 | continue; |
606 | sector = this_ext + mbr[i].mbrp_start; | | 606 | sector = this_ext + mbr[i].mbrp_start; |
607 | if (dflt_lbl->d_npartitions >= MAXPARTITIONS) | | 607 | if (dflt_lbl->d_npartitions >= MAXPARTITIONS) |
608 | continue; | | 608 | continue; |
609 | p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++]; | | 609 | p = &dflt_lbl->d_partitions[dflt_lbl->d_npartitions++]; |
610 | p->p_offset = sector; | | 610 | p->p_offset = sector; |
611 | p->p_size = mbr[i].mbrp_size; | | 611 | p->p_size = mbr[i].mbrp_size; |
612 | p->p_fstype = xlat_mbr_fstype(typ); | | 612 | p->p_fstype = xlat_mbr_fstype(typ); |
613 | } | | 613 | } |
614 | return 0; | | 614 | return 0; |
615 | } | | 615 | } |
616 | | | 616 | |
617 | #if defined(EFIBOOT) && defined(SUPPORT_CD9660) | | 617 | #if defined(EFIBOOT) && defined(SUPPORT_CD9660) |
618 | static int | | 618 | static int |
619 | check_cd9660(struct biosdisk *d) | | 619 | check_cd9660(struct biosdisk *d) |
620 | { | | 620 | { |
621 | struct biosdisk_extinfo ed; | | 621 | struct biosdisk_extinfo ed; |
622 | struct iso_primary_descriptor *vd; | | 622 | struct iso_primary_descriptor *vd; |
623 | daddr_t bno; | | 623 | daddr_t bno; |
624 | | | 624 | |
625 | for (bno = 16;; bno++) { | | 625 | for (bno = 16;; bno++) { |
626 | if (readsects(&d->ll, bno, 1, d->buf, 0)) | | 626 | if (readsects(&d->ll, bno, 1, d->buf, 0)) |
627 | return -1; | | 627 | return -1; |
628 | vd = (struct iso_primary_descriptor *)d->buf; | | 628 | vd = (struct iso_primary_descriptor *)d->buf; |
629 | if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) | | 629 | if (memcmp(vd->id, ISO_STANDARD_ID, sizeof vd->id) != 0) |
630 | return -1; | | 630 | return -1; |
631 | if (isonum_711(vd->type) == ISO_VD_END) | | 631 | if (isonum_711(vd->type) == ISO_VD_END) |
632 | return -1; | | 632 | return -1; |
633 | if (isonum_711(vd->type) == ISO_VD_PRIMARY) | | 633 | if (isonum_711(vd->type) == ISO_VD_PRIMARY) |
634 | break; | | 634 | break; |
635 | } | | 635 | } |
636 | if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) | | 636 | if (isonum_723(vd->logical_block_size) != ISO_DEFAULT_BLOCK_SIZE) |
637 | return -1; | | 637 | return -1; |
638 | | | 638 | |
639 | if (set_geometry(&d->ll, &ed)) | | 639 | if (set_geometry(&d->ll, &ed)) |
640 | return -1; | | 640 | return -1; |
641 | | | 641 | |
642 | memset(d->part, 0, sizeof(d->part)); | | 642 | memset(d->part, 0, sizeof(d->part)); |
643 | d->part[0].fstype = FS_ISO9660; | | 643 | d->part[0].fstype = FS_ISO9660; |
644 | d->part[0].offset = 0; | | 644 | d->part[0].offset = 0; |
645 | d->part[0].size = ed.totsec; | | 645 | d->part[0].size = ed.totsec; |
646 | return 0; | | 646 | return 0; |
647 | } | | 647 | } |
648 | #endif | | 648 | #endif |
649 | | | 649 | |
650 | static int | | 650 | static int |
651 | read_label(struct biosdisk *d, daddr_t offset) | | 651 | read_label(struct biosdisk *d, daddr_t offset) |
652 | { | | 652 | { |
653 | struct disklabel dflt_lbl; | | 653 | struct disklabel dflt_lbl; |
654 | struct mbr_partition mbr[MBR_PART_COUNT]; | | 654 | struct mbr_partition mbr[MBR_PART_COUNT]; |
655 | struct partition *p; | | 655 | struct partition *p; |
656 | uint32_t sector; | | 656 | uint32_t sector; |
657 | int i; | | 657 | int i; |
658 | int error; | | 658 | int error; |
659 | int typ; | | 659 | int typ; |
660 | uint32_t ext_base, this_ext, next_ext; | | 660 | uint32_t ext_base, this_ext, next_ext; |
661 | #ifdef COMPAT_386BSD_MBRPART | | 661 | #ifdef COMPAT_386BSD_MBRPART |
662 | int sector_386bsd = -1; | | 662 | int sector_386bsd = -1; |
663 | #endif | | 663 | #endif |
664 | | | 664 | |
665 | memset(&dflt_lbl, 0, sizeof(dflt_lbl)); | | 665 | memset(&dflt_lbl, 0, sizeof(dflt_lbl)); |
666 | dflt_lbl.d_npartitions = 8; | | 666 | dflt_lbl.d_npartitions = 8; |
667 | | | 667 | |
668 | d->boff = 0; | | 668 | d->boff = 0; |
669 | | | 669 | |
670 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 670 | if (d->ll.type != BIOSDISK_TYPE_HD) |
671 | /* No label on floppy and CD */ | | 671 | /* No label on floppy and CD */ |
672 | return -1; | | 672 | return -1; |
673 | | | 673 | |
674 | /* | | 674 | /* |
675 | * find NetBSD Partition in DOS partition table | | 675 | * find NetBSD Partition in DOS partition table |
676 | * XXX check magic??? | | 676 | * XXX check magic??? |
677 | */ | | 677 | */ |
678 | ext_base = offset; | | 678 | ext_base = offset; |
679 | next_ext = offset; | | 679 | next_ext = offset; |
680 | for (;;) { | | 680 | for (;;) { |
681 | this_ext = ext_base + next_ext; | | 681 | this_ext = ext_base + next_ext; |
682 | next_ext = offset; | | 682 | next_ext = offset; |
683 | if (readsects(&d->ll, this_ext, 1, d->buf, 0)) { | | 683 | if (readsects(&d->ll, this_ext, 1, d->buf, 0)) { |
684 | #ifdef DISK_DEBUG | | 684 | #ifdef DISK_DEBUG |
685 | printf("error reading MBR sector %u\n", this_ext); | | 685 | printf("error reading MBR sector %u\n", this_ext); |
686 | #endif | | 686 | #endif |
687 | return EIO; | | 687 | return EIO; |
688 | } | | 688 | } |
689 | memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr)); | | 689 | memcpy(&mbr, MBR_PARTS(d->buf), sizeof(mbr)); |
690 | /* Look for NetBSD partition ID */ | | 690 | /* Look for NetBSD partition ID */ |
691 | for (i = 0; i < MBR_PART_COUNT; i++) { | | 691 | for (i = 0; i < MBR_PART_COUNT; i++) { |
692 | typ = mbr[i].mbrp_type; | | 692 | typ = mbr[i].mbrp_type; |
693 | if (typ == 0) | | 693 | if (typ == 0) |
694 | continue; | | 694 | continue; |
695 | sector = this_ext + mbr[i].mbrp_start; | | 695 | sector = this_ext + mbr[i].mbrp_start; |
696 | #ifdef DISK_DEBUG | | 696 | #ifdef DISK_DEBUG |
697 | printf("ptn type %d in sector %u\n", typ, sector); | | 697 | printf("ptn type %d in sector %u\n", typ, sector); |
698 | #endif | | 698 | #endif |
699 | if (typ == MBR_PTYPE_MINIX_14B) { | | 699 | if (typ == MBR_PTYPE_MINIX_14B) { |
700 | if (!read_minix_subp(d, &dflt_lbl, | | 700 | if (!read_minix_subp(d, &dflt_lbl, |
701 | this_ext, sector)) { | | 701 | this_ext, sector)) { |
702 | /* Don't add "container" partition */ | | 702 | /* Don't add "container" partition */ |
703 | continue; | | 703 | continue; |
704 | } | | 704 | } |
705 | } | | 705 | } |
706 | if (typ == MBR_PTYPE_NETBSD) { | | 706 | if (typ == MBR_PTYPE_NETBSD) { |
707 | error = check_label(d, sector); | | 707 | error = check_label(d, sector); |
708 | if (error >= 0) | | 708 | if (error >= 0) |
709 | return error; | | 709 | return error; |
710 | } | | 710 | } |
711 | if (MBR_IS_EXTENDED(typ)) { | | 711 | if (MBR_IS_EXTENDED(typ)) { |
712 | next_ext = mbr[i].mbrp_start + offset; | | 712 | next_ext = mbr[i].mbrp_start + offset; |
713 | continue; | | 713 | continue; |
714 | } | | 714 | } |
715 | #ifdef COMPAT_386BSD_MBRPART | | 715 | #ifdef COMPAT_386BSD_MBRPART |
716 | if (this_ext == offset && typ == MBR_PTYPE_386BSD) | | 716 | if (this_ext == offset && typ == MBR_PTYPE_386BSD) |
717 | sector_386bsd = sector; | | 717 | sector_386bsd = sector; |
718 | #endif | | 718 | #endif |
719 | if (this_ext != offset) { | | 719 | if (this_ext != offset) { |
720 | if (dflt_lbl.d_npartitions >= MAXPARTITIONS) | | 720 | if (dflt_lbl.d_npartitions >= MAXPARTITIONS) |
721 | continue; | | 721 | continue; |
722 | p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++]; | | 722 | p = &dflt_lbl.d_partitions[dflt_lbl.d_npartitions++]; |
723 | } else | | 723 | } else |
724 | p = &dflt_lbl.d_partitions[i]; | | 724 | p = &dflt_lbl.d_partitions[i]; |
725 | p->p_offset = sector; | | 725 | p->p_offset = sector; |
726 | p->p_size = mbr[i].mbrp_size; | | 726 | p->p_size = mbr[i].mbrp_size; |
727 | p->p_fstype = xlat_mbr_fstype(typ); | | 727 | p->p_fstype = xlat_mbr_fstype(typ); |
728 | } | | 728 | } |
729 | if (next_ext == offset) | | 729 | if (next_ext == offset) |
730 | break; | | 730 | break; |
731 | if (ext_base == offset) { | | 731 | if (ext_base == offset) { |
732 | ext_base = next_ext; | | 732 | ext_base = next_ext; |
733 | next_ext = offset; | | 733 | next_ext = offset; |
734 | } | | 734 | } |
735 | } | | 735 | } |
736 | | | 736 | |
737 | sector = offset; | | 737 | sector = offset; |
738 | #ifdef COMPAT_386BSD_MBRPART | | 738 | #ifdef COMPAT_386BSD_MBRPART |
739 | if (sector_386bsd != -1) { | | 739 | if (sector_386bsd != -1) { |
740 | printf("old BSD partition ID!\n"); | | 740 | printf("old BSD partition ID!\n"); |
741 | sector = sector_386bsd; | | 741 | sector = sector_386bsd; |
742 | } | | 742 | } |
743 | #endif | | 743 | #endif |
744 | | | 744 | |
745 | /* | | 745 | /* |
746 | * One of two things: | | 746 | * One of two things: |
747 | * 1. no MBR | | 747 | * 1. no MBR |
748 | * 2. no NetBSD partition in MBR | | 748 | * 2. no NetBSD partition in MBR |
749 | * | | 749 | * |
750 | * We simply default to "start of disk" in this case and | | 750 | * We simply default to "start of disk" in this case and |
751 | * press on. | | 751 | * press on. |
752 | */ | | 752 | */ |
753 | error = check_label(d, sector); | | 753 | error = check_label(d, sector); |
754 | if (error >= 0) | | 754 | if (error >= 0) |
755 | return error; | | 755 | return error; |
756 | | | 756 | |
757 | #if defined(EFIBOOT) && defined(SUPPORT_CD9660) | | 757 | #if defined(EFIBOOT) && defined(SUPPORT_CD9660) |
758 | /* Check CD/DVD */ | | 758 | /* Check CD/DVD */ |
759 | error = check_cd9660(d); | | 759 | error = check_cd9660(d); |
760 | if (error >= 0) | | 760 | if (error >= 0) |
761 | return error; | | 761 | return error; |
762 | #endif | | 762 | #endif |
763 | | | 763 | |
764 | /* | | 764 | /* |
765 | * Nothing at start of disk, return info from mbr partitions. | | 765 | * Nothing at start of disk, return info from mbr partitions. |
766 | */ | | 766 | */ |
767 | /* XXX fill it to make checksum match kernel one */ | | 767 | /* XXX fill it to make checksum match kernel one */ |
768 | dflt_lbl.d_checksum = dkcksum(&dflt_lbl); | | 768 | dflt_lbl.d_checksum = dkcksum(&dflt_lbl); |
769 | ingest_label(d, &dflt_lbl); | | 769 | ingest_label(d, &dflt_lbl); |
770 | return 0; | | 770 | return 0; |
771 | } | | 771 | } |
772 | #endif /* NO_DISKLABEL */ | | 772 | #endif /* NO_DISKLABEL */ |
773 | | | 773 | |
774 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 774 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
775 | static int | | 775 | static int |
776 | read_partitions(struct biosdisk *d, daddr_t offset, daddr_t size) | | 776 | read_partitions(struct biosdisk *d, daddr_t offset, daddr_t size) |
777 | { | | 777 | { |
778 | int error; | | 778 | int error; |
779 | | | 779 | |
780 | error = -1; | | 780 | error = -1; |
781 | | | 781 | |
782 | #ifndef NO_GPT | | 782 | #ifndef NO_GPT |
783 | error = read_gpt(d, offset, size); | | 783 | error = read_gpt(d, offset, size); |
784 | if (error == 0) | | 784 | if (error == 0) |
785 | return 0; | | 785 | return 0; |
786 | | | 786 | |
787 | #endif | | 787 | #endif |
788 | #ifndef NO_DISKLABEL | | 788 | #ifndef NO_DISKLABEL |
789 | error = read_label(d, offset); | | 789 | error = read_label(d, offset); |
790 | | | 790 | |
791 | #endif | | 791 | #endif |
792 | return error; | | 792 | return error; |
793 | } | | 793 | } |
794 | #endif | | 794 | #endif |
795 | | | 795 | |
796 | #ifndef NO_RAIDFRAME | | 796 | #ifndef NO_RAIDFRAME |
797 | static void | | 797 | static void |
798 | raidframe_probe(struct raidframe *raidframe, int *raidframe_count, | | 798 | raidframe_probe(struct raidframe *raidframe, int *raidframe_count, |
799 | struct biosdisk *d, int part) | | 799 | struct biosdisk *d, int part) |
800 | { | | 800 | { |
801 | int i = *raidframe_count; | | 801 | int i = *raidframe_count; |
802 | struct RF_ComponentLabel_s label; | | 802 | struct RF_ComponentLabel_s label; |
803 | daddr_t offset; | | 803 | daddr_t offset; |
804 | | | 804 | |
805 | if (i + 1 > RAIDFRAME_NDEV) | | 805 | if (i + 1 > RAIDFRAME_NDEV) |
806 | return; | | 806 | return; |
807 | | | 807 | |
808 | offset = d->part[part].offset; | | 808 | offset = d->part[part].offset; |
809 | if ((biosdisk_read_raidframe(d->ll.dev, offset, &label)) != 0) | | 809 | if ((biosdisk_read_raidframe(d->ll.dev, offset, &label)) != 0) |
810 | return; | | 810 | return; |
811 | | | 811 | |
812 | if (label.version != RF_COMPONENT_LABEL_VERSION) | | 812 | if (label.version != RF_COMPONENT_LABEL_VERSION) |
813 | printf("Unexpected raidframe label version\n"); | | 813 | printf("Unexpected raidframe label version\n"); |
814 | | | 814 | |
815 | raidframe[i].last_unit = label.last_unit; | | 815 | raidframe[i].last_unit = label.last_unit; |
816 | raidframe[i].serial = label.serial_number; | | 816 | raidframe[i].serial = label.serial_number; |
817 | raidframe[i].biosdev = d->ll.dev; | | 817 | raidframe[i].biosdev = d->ll.dev; |
818 | raidframe[i].parent_part = part; | | 818 | raidframe[i].parent_part = part; |
819 | #ifndef NO_GPT | | 819 | #ifndef NO_GPT |
820 | if (d->part[part].part_name) | | 820 | if (d->part[part].part_name) |
821 | strlcpy(raidframe[i].parent_name, | | 821 | strlcpy(raidframe[i].parent_name, |
822 | d->part[part].part_name, MAXDEVNAME); | | 822 | d->part[part].part_name, MAXDEVNAME); |
823 | else | | 823 | else |
824 | raidframe[i].parent_name[0] = '\0'; | | 824 | raidframe[i].parent_name[0] = '\0'; |
825 | #endif | | 825 | #endif |
826 | raidframe[i].offset = offset; | | 826 | raidframe[i].offset = offset; |
827 | raidframe[i].size = label.__numBlocks; | | 827 | raidframe[i].size = label.__numBlocks; |
828 | | | 828 | |
829 | (*raidframe_count)++; | | 829 | (*raidframe_count)++; |
830 | | | 830 | |
831 | return; | | 831 | return; |
832 | } | | 832 | } |
833 | #endif | | 833 | #endif |
834 | | | 834 | |
835 | void | | 835 | void |
836 | biosdisk_probe(void) | | 836 | biosdisk_probe(void) |
837 | { | | 837 | { |
838 | struct biosdisk *d; | | 838 | struct biosdisk *d; |
839 | struct biosdisk_extinfo ed; | | 839 | struct biosdisk_extinfo ed; |
840 | #ifndef NO_RAIDFRAME | | 840 | #ifndef NO_RAIDFRAME |
841 | struct raidframe raidframe[RAIDFRAME_NDEV]; | | 841 | struct raidframe raidframe[RAIDFRAME_NDEV]; |
842 | int raidframe_count = 0; | | 842 | int raidframe_count = 0; |
843 | #endif | | 843 | #endif |
844 | uint64_t size; | | 844 | uint64_t size; |
845 | int first; | | 845 | int first; |
846 | int i; | | 846 | int i; |
847 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 847 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
848 | int part; | | 848 | int part; |
849 | #endif | | 849 | #endif |
850 | | | 850 | |
851 | for (i = 0; i < MAX_BIOSDISKS + 2; i++) { | | 851 | for (i = 0; i < MAX_BIOSDISKS + 2; i++) { |
852 | first = 1; | | 852 | first = 1; |
853 | d = alloc(sizeof(*d)); | | 853 | d = alloc(sizeof(*d)); |
854 | if (d == NULL) { | | 854 | if (d == NULL) { |
855 | printf("Out of memory\n"); | | 855 | printf("Out of memory\n"); |
856 | return; | | 856 | return; |
857 | } | | 857 | } |
858 | memset(d, 0, sizeof(*d)); | | 858 | memset(d, 0, sizeof(*d)); |
859 | memset(&ed, 0, sizeof(ed)); | | 859 | memset(&ed, 0, sizeof(ed)); |
860 | if (i >= MAX_BIOSDISKS) | | 860 | if (i >= MAX_BIOSDISKS) |
861 | d->ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ | | 861 | d->ll.dev = 0x00 + i - MAX_BIOSDISKS; /* fd */ |
862 | else | | 862 | else |
863 | d->ll.dev = 0x80 + i; /* hd/cd */ | | 863 | d->ll.dev = 0x80 + i; /* hd/cd */ |
864 | if (set_geometry(&d->ll, &ed)) | | 864 | if (set_geometry(&d->ll, &ed)) |
865 | goto next_disk; | | 865 | goto next_disk; |
866 | printf("disk "); | | 866 | printf("disk "); |
867 | switch (d->ll.type) { | | 867 | switch (d->ll.type) { |
868 | case BIOSDISK_TYPE_CD: | | 868 | case BIOSDISK_TYPE_CD: |
869 | printf("cd0\n cd0a\n"); | | 869 | printf("cd0\n cd0a\n"); |
870 | break; | | 870 | break; |
871 | case BIOSDISK_TYPE_FD: | | 871 | case BIOSDISK_TYPE_FD: |
872 | printf("fd%d\n", d->ll.dev & 0x7f); | | 872 | printf("fd%d\n", d->ll.dev & 0x7f); |
873 | printf(" fd%da\n", d->ll.dev & 0x7f); | | 873 | printf(" fd%da\n", d->ll.dev & 0x7f); |
874 | break; | | 874 | break; |
875 | case BIOSDISK_TYPE_HD: | | 875 | case BIOSDISK_TYPE_HD: |
876 | printf("hd%d", d->ll.dev & 0x7f); | | 876 | printf("hd%d", d->ll.dev & 0x7f); |
877 | if (d->ll.flags & BIOSDISK_INT13EXT) { | | 877 | if (d->ll.flags & BIOSDISK_INT13EXT) { |
878 | printf(" size "); | | 878 | printf(" size "); |
879 | size = ed.totsec * ed.sbytes; | | 879 | size = ed.totsec * ed.sbytes; |
880 | if (size >= (10ULL * 1024 * 1024 * 1024)) | | 880 | if (size >= (10ULL * 1024 * 1024 * 1024)) |
881 | printf("%"PRIu64" GB", | | 881 | printf("%"PRIu64" GB", |
882 | size / (1024 * 1024 * 1024)); | | 882 | size / (1024 * 1024 * 1024)); |
883 | else | | 883 | else |
884 | printf("%"PRIu64" MB", | | 884 | printf("%"PRIu64" MB", |
885 | size / (1024 * 1024)); | | 885 | size / (1024 * 1024)); |
886 | } | | 886 | } |
887 | printf("\n"); | | 887 | printf("\n"); |
888 | break; | | 888 | break; |
889 | } | | 889 | } |
890 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 890 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
891 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 891 | if (d->ll.type != BIOSDISK_TYPE_HD) |
892 | goto next_disk; | | 892 | goto next_disk; |
893 | | | 893 | |
894 | if (read_partitions(d, 0, 0) != 0) | | 894 | if (read_partitions(d, 0, 0) != 0) |
895 | goto next_disk; | | 895 | goto next_disk; |
896 | | | 896 | |
897 | for (part = 0; part < BIOSDISKNPART; part++) { | | 897 | for (part = 0; part < BIOSDISKNPART; part++) { |
898 | if (d->part[part].size == 0) | | 898 | if (d->part[part].size == 0) |
899 | continue; | | 899 | continue; |
900 | if (d->part[part].fstype == FS_UNUSED) | | 900 | if (d->part[part].fstype == FS_UNUSED) |
901 | continue; | | 901 | continue; |
902 | #ifndef NO_RAIDFRAME | | 902 | #ifndef NO_RAIDFRAME |
903 | if (d->part[part].fstype == FS_RAID) | | 903 | if (d->part[part].fstype == FS_RAID) |
904 | raidframe_probe(raidframe, | | 904 | raidframe_probe(raidframe, |
905 | &raidframe_count, d, part); | | 905 | &raidframe_count, d, part); |
906 | #endif | | 906 | #endif |
907 | if (first) { | | 907 | if (first) { |
908 | printf(" "); | | 908 | printf(" "); |
909 | first = 0; | | 909 | first = 0; |
910 | } | | 910 | } |
911 | #ifndef NO_GPT | | 911 | #ifndef NO_GPT |
912 | if (d->part[part].part_name && | | 912 | if (d->part[part].part_name && |
913 | d->part[part].part_name[0]) | | 913 | d->part[part].part_name[0]) |
914 | printf(" NAME=%s(", d->part[part].part_name); | | 914 | printf(" NAME=%s(", d->part[part].part_name); |
915 | else | | 915 | else |
916 | #endif | | 916 | #endif |
917 | printf(" hd%d%c(", d->ll.dev & 0x7f, part + 'a'); | | 917 | printf(" hd%d%c(", d->ll.dev & 0x7f, part + 'a'); |
918 | | | 918 | |
919 | #ifndef NO_GPT | | 919 | #ifndef NO_GPT |
920 | if (d->part[part].guid != NULL) | | 920 | if (d->part[part].guid != NULL) |
921 | printf("%s", d->part[part].guid->name); | | 921 | printf("%s", d->part[part].guid->name); |
922 | else | | 922 | else |
923 | #endif | | 923 | #endif |
924 | | | 924 | |
925 | if (d->part[part].fstype < FSMAXTYPES) | | 925 | if (d->part[part].fstype < FSMAXTYPES) |
926 | printf("%s", | | 926 | printf("%s", |
927 | fstypenames[d->part[part].fstype]); | | 927 | fstypenames[d->part[part].fstype]); |
928 | else | | 928 | else |
929 | printf("%d", d->part[part].fstype); | | 929 | printf("%d", d->part[part].fstype); |
930 | printf(")"); | | 930 | printf(")"); |
931 | } | | 931 | } |
932 | #endif | | 932 | #endif |
933 | if (first == 0) | | 933 | if (first == 0) |
934 | printf("\n"); | | 934 | printf("\n"); |
935 | | | 935 | |
936 | next_disk: | | 936 | next_disk: |
937 | dealloc_biosdisk(d); | | 937 | dealloc_biosdisk(d); |
938 | } | | 938 | } |
939 | | | 939 | |
940 | #ifndef NO_RAIDFRAME | | 940 | #ifndef NO_RAIDFRAME |
941 | for (i = 0; i < raidframe_count; i++) { | | 941 | for (i = 0; i < raidframe_count; i++) { |
942 | size_t secsize; | | 942 | size_t secsize; |
943 | | | 943 | |
944 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { | | 944 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { |
945 | printf("Out of memory\n"); | | 945 | printf("Out of memory\n"); |
946 | return; | | 946 | return; |
947 | } | | 947 | } |
948 | | | 948 | |
949 | secsize = d->ll.secsize; | | 949 | secsize = d->ll.secsize; |
950 | | | 950 | |
951 | printf("raidframe raid%d serial %d in ", | | 951 | printf("raidframe raid%d serial %d in ", |
952 | raidframe[i].last_unit, raidframe[i].serial); | | 952 | raidframe[i].last_unit, raidframe[i].serial); |
953 | #ifndef NO_GPT | | 953 | #ifndef NO_GPT |
954 | if (raidframe[i].parent_name[0]) | | 954 | if (raidframe[i].parent_name[0]) |
955 | printf("NAME=%s size ", raidframe[i].parent_name); | | 955 | printf("NAME=%s size ", raidframe[i].parent_name); |
956 | else | | 956 | else |
957 | #endif | | 957 | #endif |
958 | printf("hd%d%c size ", d->ll.dev & 0x7f, | | 958 | printf("hd%d%c size ", d->ll.dev & 0x7f, |
959 | raidframe[i].parent_part + 'a'); | | 959 | raidframe[i].parent_part + 'a'); |
960 | if (raidframe[i].size >= (10ULL * 1024 * 1024 * 1024 / secsize)) | | 960 | if (raidframe[i].size >= (10ULL * 1024 * 1024 * 1024 / secsize)) |
961 | printf("%"PRIu64" GB", | | 961 | printf("%"PRIu64" GB", |
962 | raidframe[i].size / (1024 * 1024 * 1024 / secsize)); | | 962 | raidframe[i].size / (1024 * 1024 * 1024 / secsize)); |
963 | else | | 963 | else |
964 | printf("%"PRIu64" MB", | | 964 | printf("%"PRIu64" MB", |
965 | raidframe[i].size / (1024 * 1024 / secsize)); | | 965 | raidframe[i].size / (1024 * 1024 / secsize)); |
966 | printf("\n"); | | 966 | printf("\n"); |
967 | | | 967 | |
968 | if (read_partitions(d, | | 968 | if (read_partitions(d, |
969 | raidframe[i].offset + RF_PROTECTED_SECTORS, | | 969 | raidframe[i].offset + RF_PROTECTED_SECTORS, |
970 | raidframe[i].size) != 0) | | 970 | raidframe[i].size) != 0) |
971 | goto next_raidrame; | | 971 | goto next_raidrame; |
972 | | | 972 | |
973 | first = 1; | | 973 | first = 1; |
974 | for (part = 0; part < BIOSDISKNPART; part++) { | | 974 | for (part = 0; part < BIOSDISKNPART; part++) { |
975 | #ifndef NO_GPT | | 975 | #ifndef NO_GPT |
976 | bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; | | 976 | bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; |
977 | #else | | 977 | #else |
978 | bool bootme = 0; | | 978 | bool bootme = 0; |
979 | #endif | | 979 | #endif |
980 | | | 980 | |
981 | if (d->part[part].size == 0) | | 981 | if (d->part[part].size == 0) |
982 | continue; | | 982 | continue; |
983 | if (d->part[part].fstype == FS_UNUSED) | | 983 | if (d->part[part].fstype == FS_UNUSED) |
984 | continue; | | 984 | continue; |
985 | if (d->part[part].fstype == FS_RAID) | | 985 | if (d->part[part].fstype == FS_RAID) |
986 | continue; | | 986 | continue; |
987 | if (first) { | | 987 | if (first) { |
988 | printf(" "); | | 988 | printf(" "); |
989 | first = 0; | | 989 | first = 0; |
990 | } | | 990 | } |
991 | #ifndef NO_GPT | | 991 | #ifndef NO_GPT |
992 | if (d->part[part].part_name && | | 992 | if (d->part[part].part_name && |
993 | d->part[part].part_name[0]) | | 993 | d->part[part].part_name[0]) |
994 | printf(" NAME=%s(", d->part[part].part_name); | | 994 | printf(" NAME=%s(", d->part[part].part_name); |
995 | else | | 995 | else |
996 | #endif | | 996 | #endif |
997 | printf(" raid%d%c(", raidframe[i].last_unit, | | 997 | printf(" raid%d%c(", raidframe[i].last_unit, |
998 | part + 'a'); | | 998 | part + 'a'); |
999 | #ifndef NO_GPT | | 999 | #ifndef NO_GPT |
1000 | if (d->part[part].guid != NULL) | | 1000 | if (d->part[part].guid != NULL) |
1001 | printf("%s", d->part[part].guid->name); | | 1001 | printf("%s", d->part[part].guid->name); |
1002 | else | | 1002 | else |
1003 | #endif | | 1003 | #endif |
1004 | if (d->part[part].fstype < FSMAXTYPES) | | 1004 | if (d->part[part].fstype < FSMAXTYPES) |
1005 | printf("%s", | | 1005 | printf("%s", |
1006 | fstypenames[d->part[part].fstype]); | | 1006 | fstypenames[d->part[part].fstype]); |
1007 | else | | 1007 | else |
1008 | printf("%d", d->part[part].fstype); | | 1008 | printf("%d", d->part[part].fstype); |
1009 | printf("%s)", bootme ? ", bootme" : ""); | | 1009 | printf("%s)", bootme ? ", bootme" : ""); |
1010 | } | | 1010 | } |
1011 | | | 1011 | |
1012 | next_raidrame: | | 1012 | next_raidrame: |
1013 | if (first == 0) | | 1013 | if (first == 0) |
1014 | printf("\n"); | | 1014 | printf("\n"); |
1015 | | | 1015 | |
1016 | dealloc_biosdisk(d); | | 1016 | dealloc_biosdisk(d); |
1017 | } | | 1017 | } |
1018 | #endif | | 1018 | #endif |
1019 | } | | 1019 | } |
1020 | | | 1020 | |
1021 | /* Determine likely partition for possible sector number of dos | | 1021 | /* Determine likely partition for possible sector number of dos |
1022 | * partition. | | 1022 | * partition. |
1023 | */ | | 1023 | */ |
1024 | | | 1024 | |
1025 | int | | 1025 | int |
1026 | biosdisk_findpartition(int biosdev, daddr_t sector, | | 1026 | biosdisk_findpartition(int biosdev, daddr_t sector, |
1027 | int *partition, const char **part_name) | | 1027 | int *partition, const char **part_name) |
1028 | { | | 1028 | { |
1029 | #if defined(NO_DISKLABEL) && defined(NO_GPT) | | 1029 | #if defined(NO_DISKLABEL) && defined(NO_GPT) |
1030 | *partition = 0; | | 1030 | *partition = 0; |
1031 | *part_name = NULL; | | 1031 | if (part_name) |
| | | 1032 | *part_name = NULL; |
1032 | return 0; | | 1033 | return 0; |
1033 | #else | | 1034 | #else |
1034 | int i; | | 1035 | int i; |
1035 | struct biosdisk *d; | | 1036 | struct biosdisk *d; |
1036 | int biosboot_sector_part = -1; | | 1037 | int biosboot_sector_part = -1; |
1037 | int bootable_fs_part = -1; | | 1038 | int bootable_fs_part = -1; |
1038 | int boot_part = 0; | | 1039 | int boot_part = 0; |
1039 | #ifndef NO_GPT | | 1040 | #ifndef NO_GPT |
1040 | int gpt_bootme_part = -1; | | 1041 | int gpt_bootme_part = -1; |
1041 | static char namebuf[MAXDEVNAME + 1]; | | 1042 | static char namebuf[MAXDEVNAME + 1]; |
1042 | #endif | | 1043 | #endif |
1043 | | | 1044 | |
1044 | #ifdef DISK_DEBUG | | 1045 | #ifdef DISK_DEBUG |
1045 | printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector); | | 1046 | printf("looking for partition device %x, sector %"PRId64"\n", biosdev, sector); |
1046 | #endif | | 1047 | #endif |
1047 | | | 1048 | |
1048 | /* default to first partition */ | | 1049 | /* default to first partition */ |
1049 | *partition = 0; | | 1050 | *partition = 0; |
1050 | *part_name = NULL; | | 1051 | if (part_name) |
| | | 1052 | *part_name = NULL; |
1051 | | | 1053 | |
1052 | /* Look for netbsd partition that is the dos boot one */ | | 1054 | /* Look for netbsd partition that is the dos boot one */ |
1053 | d = alloc_biosdisk(biosdev); | | 1055 | d = alloc_biosdisk(biosdev); |
1054 | if (d == NULL) | | 1056 | if (d == NULL) |
1055 | return -1; | | 1057 | return -1; |
1056 | | | 1058 | |
1057 | if (read_partitions(d, 0, 0) == 0) { | | 1059 | if (read_partitions(d, 0, 0) == 0) { |
1058 | for (i = 0; i < BIOSDISKNPART; i++) { | | 1060 | for (i = 0; i < BIOSDISKNPART; i++) { |
1059 | if (d->part[i].fstype == FS_UNUSED) | | 1061 | if (d->part[i].fstype == FS_UNUSED) |
1060 | continue; | | 1062 | continue; |
1061 | | | 1063 | |
1062 | if (d->part[i].offset == sector && | | 1064 | if (d->part[i].offset == sector && |
1063 | biosboot_sector_part == -1) | | 1065 | biosboot_sector_part == -1) |
1064 | biosboot_sector_part = i; | | 1066 | biosboot_sector_part = i; |
1065 | | | 1067 | |
1066 | #ifndef NO_GPT | | 1068 | #ifndef NO_GPT |
1067 | if (d->part[i].attr & GPT_ENT_ATTR_BOOTME && | | 1069 | if (d->part[i].attr & GPT_ENT_ATTR_BOOTME && |
1068 | gpt_bootme_part == -1) | | 1070 | gpt_bootme_part == -1) |
1069 | gpt_bootme_part = i; | | 1071 | gpt_bootme_part = i; |
1070 | #endif | | 1072 | #endif |
1071 | switch (d->part[i].fstype) { | | 1073 | switch (d->part[i].fstype) { |
1072 | case FS_BSDFFS: | | 1074 | case FS_BSDFFS: |
1073 | case FS_BSDLFS: | | 1075 | case FS_BSDLFS: |
1074 | case FS_RAID: | | 1076 | case FS_RAID: |
1075 | case FS_CCD: | | 1077 | case FS_CCD: |
1076 | case FS_CGD: | | 1078 | case FS_CGD: |
1077 | case FS_ISO9660: | | 1079 | case FS_ISO9660: |
1078 | if (bootable_fs_part == -1) | | 1080 | if (bootable_fs_part == -1) |
1079 | bootable_fs_part = i; | | 1081 | bootable_fs_part = i; |
1080 | break; | | 1082 | break; |
1081 | | | 1083 | |
1082 | default: | | 1084 | default: |
1083 | break; | | 1085 | break; |
1084 | } | | 1086 | } |
1085 | } | | 1087 | } |
1086 | | | 1088 | |
1087 | #ifndef NO_GPT | | 1089 | #ifndef NO_GPT |
1088 | if (gpt_bootme_part != -1) | | 1090 | if (gpt_bootme_part != -1) |
1089 | boot_part = gpt_bootme_part; | | 1091 | boot_part = gpt_bootme_part; |
1090 | else | | 1092 | else |
1091 | #endif | | 1093 | #endif |
1092 | if (biosboot_sector_part != -1) | | 1094 | if (biosboot_sector_part != -1) |
1093 | boot_part = biosboot_sector_part; | | 1095 | boot_part = biosboot_sector_part; |
1094 | else if (bootable_fs_part != -1) | | 1096 | else if (bootable_fs_part != -1) |
1095 | boot_part = bootable_fs_part; | | 1097 | boot_part = bootable_fs_part; |
1096 | else | | 1098 | else |
1097 | boot_part = 0; | | 1099 | boot_part = 0; |
1098 | | | 1100 | |
1099 | *partition = boot_part; | | 1101 | *partition = boot_part; |
1100 | #ifndef NO_GPT | | 1102 | #ifndef NO_GPT |
1101 | if (part_name && | | 1103 | if (part_name && |
1102 | d->part[boot_part].part_name && | | 1104 | d->part[boot_part].part_name && |
1103 | d->part[boot_part].part_name[0]) { | | 1105 | d->part[boot_part].part_name[0]) { |
1104 | strlcpy(namebuf, d->part[boot_part].part_name, | | 1106 | strlcpy(namebuf, d->part[boot_part].part_name, |
1105 | BIOSDISK_PART_NAME_LEN); | | 1107 | BIOSDISK_PART_NAME_LEN); |
1106 | *part_name = namebuf; | | 1108 | *part_name = namebuf; |
1107 | } | | 1109 | } |
1108 | #endif | | 1110 | #endif |
1109 | } | | 1111 | } |
1110 | | | 1112 | |
1111 | dealloc_biosdisk(d); | | 1113 | dealloc_biosdisk(d); |
1112 | return 0; | | 1114 | return 0; |
1113 | #endif /* NO_DISKLABEL && NO_GPT */ | | 1115 | #endif /* NO_DISKLABEL && NO_GPT */ |
1114 | } | | 1116 | } |
1115 | | | 1117 | |
1116 | int | | 1118 | int |
1117 | biosdisk_readpartition(int biosdev, daddr_t offset, daddr_t size, | | 1119 | biosdisk_readpartition(int biosdev, daddr_t offset, daddr_t size, |
1118 | struct biosdisk_partition **partpp, int *rnum) | | 1120 | struct biosdisk_partition **partpp, int *rnum) |
1119 | { | | 1121 | { |
1120 | #if defined(NO_DISKLABEL) && defined(NO_GPT) | | 1122 | #if defined(NO_DISKLABEL) && defined(NO_GPT) |
1121 | return ENOTSUP; | | 1123 | return ENOTSUP; |
1122 | #else | | 1124 | #else |
1123 | struct biosdisk *d; | | 1125 | struct biosdisk *d; |
1124 | struct biosdisk_partition *part; | | 1126 | struct biosdisk_partition *part; |
1125 | int rv; | | 1127 | int rv; |
1126 | | | 1128 | |
1127 | /* Look for netbsd partition that is the dos boot one */ | | 1129 | /* Look for netbsd partition that is the dos boot one */ |
1128 | d = alloc_biosdisk(biosdev); | | 1130 | d = alloc_biosdisk(biosdev); |
1129 | if (d == NULL) | | 1131 | if (d == NULL) |
1130 | return ENOMEM; | | 1132 | return ENOMEM; |
1131 | | | 1133 | |
1132 | if (read_partitions(d, offset, size)) { | | 1134 | if (read_partitions(d, offset, size)) { |
1133 | rv = EINVAL; | | 1135 | rv = EINVAL; |
1134 | goto out; | | 1136 | goto out; |
1135 | } | | 1137 | } |
1136 | | | 1138 | |
1137 | part = copy_biosdisk_part(d); | | 1139 | part = copy_biosdisk_part(d); |
1138 | if (part == NULL) { | | 1140 | if (part == NULL) { |
1139 | rv = ENOMEM; | | 1141 | rv = ENOMEM; |
1140 | goto out; | | 1142 | goto out; |
1141 | } | | 1143 | } |
1142 | | | 1144 | |
1143 | *partpp = part; | | 1145 | *partpp = part; |
1144 | *rnum = (int)__arraycount(d->part); | | 1146 | *rnum = (int)__arraycount(d->part); |
1145 | rv = 0; | | 1147 | rv = 0; |
1146 | out: | | 1148 | out: |
1147 | dealloc_biosdisk(d); | | 1149 | dealloc_biosdisk(d); |
1148 | return rv; | | 1150 | return rv; |
1149 | #endif /* NO_DISKLABEL && NO_GPT */ | | 1151 | #endif /* NO_DISKLABEL && NO_GPT */ |
1150 | } | | 1152 | } |
1151 | | | 1153 | |
1152 | #ifndef NO_RAIDFRAME | | 1154 | #ifndef NO_RAIDFRAME |
1153 | int | | 1155 | int |
1154 | biosdisk_read_raidframe(int biosdev, daddr_t offset, | | 1156 | biosdisk_read_raidframe(int biosdev, daddr_t offset, |
1155 | struct RF_ComponentLabel_s *label) | | 1157 | struct RF_ComponentLabel_s *label) |
1156 | { | | 1158 | { |
1157 | #if defined(NO_DISKLABEL) && defined(NO_GPT) | | 1159 | #if defined(NO_DISKLABEL) && defined(NO_GPT) |
1158 | return ENOTSUP; | | 1160 | return ENOTSUP; |
1159 | #else | | 1161 | #else |
1160 | struct biosdisk *d; | | 1162 | struct biosdisk *d; |
1161 | struct biosdisk_extinfo ed; | | 1163 | struct biosdisk_extinfo ed; |
1162 | daddr_t size; | | 1164 | daddr_t size; |
1163 | int rv = -1; | | 1165 | int rv = -1; |
1164 | | | 1166 | |
1165 | /* Look for netbsd partition that is the dos boot one */ | | 1167 | /* Look for netbsd partition that is the dos boot one */ |
1166 | d = alloc_biosdisk(biosdev); | | 1168 | d = alloc_biosdisk(biosdev); |
1167 | if (d == NULL) | | 1169 | if (d == NULL) |
1168 | goto out; | | 1170 | goto out; |
1169 | | | 1171 | |
1170 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 1172 | if (d->ll.type != BIOSDISK_TYPE_HD) |
1171 | /* No raidframe on floppy and CD */ | | 1173 | /* No raidframe on floppy and CD */ |
1172 | goto out; | | 1174 | goto out; |
1173 | | | 1175 | |
1174 | if (set_geometry(&d->ll, &ed) != 0) | | 1176 | if (set_geometry(&d->ll, &ed) != 0) |
1175 | goto out; | | 1177 | goto out; |
1176 | | | 1178 | |
1177 | /* Sanity check values returned from BIOS */ | | 1179 | /* Sanity check values returned from BIOS */ |
1178 | if (ed.sbytes >= 512 && | | 1180 | if (ed.sbytes >= 512 && |
1179 | (ed.sbytes & (ed.sbytes - 1)) == 0) | | 1181 | (ed.sbytes & (ed.sbytes - 1)) == 0) |
1180 | d->ll.secsize = ed.sbytes; | | 1182 | d->ll.secsize = ed.sbytes; |
1181 | | | 1183 | |
1182 | offset += (RF_COMPONENT_INFO_OFFSET / d->ll.secsize); | | 1184 | offset += (RF_COMPONENT_INFO_OFFSET / d->ll.secsize); |
1183 | size = roundup(sizeof(*label), d->ll.secsize) / d->ll.secsize; | | 1185 | size = roundup(sizeof(*label), d->ll.secsize) / d->ll.secsize; |
1184 | if (readsects(&d->ll, offset, size, d->buf, 0)) | | 1186 | if (readsects(&d->ll, offset, size, d->buf, 0)) |
1185 | goto out; | | 1187 | goto out; |
1186 | memcpy(label, d->buf, sizeof(*label)); | | 1188 | memcpy(label, d->buf, sizeof(*label)); |
1187 | rv = 0; | | 1189 | rv = 0; |
1188 | out: | | 1190 | out: |
1189 | if (d != NULL) | | 1191 | if (d != NULL) |
1190 | dealloc_biosdisk(d); | | 1192 | dealloc_biosdisk(d); |
1191 | return rv; | | 1193 | return rv; |
1192 | #endif /* NO_DISKLABEL && NO_GPT */ | | 1194 | #endif /* NO_DISKLABEL && NO_GPT */ |
1193 | } | | 1195 | } |
1194 | #endif /* NO_RAIDFRAME */ | | 1196 | #endif /* NO_RAIDFRAME */ |
1195 | | | 1197 | |
1196 | #ifdef _STANDALONE | | 1198 | #ifdef _STANDALONE |
1197 | static void | | 1199 | static void |
1198 | add_biosdisk_bootinfo(void) | | 1200 | add_biosdisk_bootinfo(void) |
1199 | { | | 1201 | { |
1200 | if (bootinfo == NULL) { | | 1202 | if (bootinfo == NULL) { |
1201 | return; | | 1203 | return; |
1202 | } | | 1204 | } |
1203 | BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); | | 1205 | BI_ADD(&bi_disk, BTINFO_BOOTDISK, sizeof(bi_disk)); |
1204 | BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge)); | | 1206 | BI_ADD(&bi_wedge, BTINFO_BOOTWEDGE, sizeof(bi_wedge)); |
1205 | return; | | 1207 | return; |
1206 | } | | 1208 | } |
1207 | #endif | | 1209 | #endif |
1208 | | | 1210 | |
1209 | #ifndef NO_GPT | | 1211 | #ifndef NO_GPT |
1210 | static daddr_t | | 1212 | static daddr_t |
1211 | raidframe_part_offset(struct biosdisk *d, int part) | | 1213 | raidframe_part_offset(struct biosdisk *d, int part) |
1212 | { | | 1214 | { |
1213 | struct biosdisk raidframe; | | 1215 | struct biosdisk raidframe; |
1214 | daddr_t rf_offset; | | 1216 | daddr_t rf_offset; |
1215 | daddr_t rf_size; | | 1217 | daddr_t rf_size; |
1216 | int i, candidate; | | 1218 | int i, candidate; |
1217 | | | 1219 | |
1218 | memset(&raidframe, 0, sizeof(raidframe)); | | 1220 | memset(&raidframe, 0, sizeof(raidframe)); |
1219 | raidframe.ll = d->ll; | | 1221 | raidframe.ll = d->ll; |
1220 | | | 1222 | |
1221 | rf_offset = d->part[part].offset + RF_PROTECTED_SECTORS; | | 1223 | rf_offset = d->part[part].offset + RF_PROTECTED_SECTORS; |
1222 | rf_size = d->part[part].size; | | 1224 | rf_size = d->part[part].size; |
1223 | if (read_gpt(&raidframe, rf_offset, rf_size) != 0) | | 1225 | if (read_gpt(&raidframe, rf_offset, rf_size) != 0) |
1224 | return RF_PROTECTED_SECTORS; | | 1226 | return RF_PROTECTED_SECTORS; |
1225 | | | 1227 | |
1226 | candidate = 0; | | 1228 | candidate = 0; |
1227 | for (i = 0; i < BIOSDISKNPART; i++) { | | 1229 | for (i = 0; i < BIOSDISKNPART; i++) { |
1228 | if (raidframe.part[i].size == 0) | | 1230 | if (raidframe.part[i].size == 0) |
1229 | continue; | | 1231 | continue; |
1230 | if (raidframe.part[i].fstype == FS_UNUSED) | | 1232 | if (raidframe.part[i].fstype == FS_UNUSED) |
1231 | continue; | | 1233 | continue; |
1232 | #ifndef NO_GPT | | 1234 | #ifndef NO_GPT |
1233 | if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME) | | 1235 | if (raidframe.part[i].attr & GPT_ENT_ATTR_BOOTME) |
1234 | candidate = i; | | 1236 | candidate = i; |
1235 | #endif | | 1237 | #endif |
1236 | } | | 1238 | } |
1237 | | | 1239 | |
1238 | return RF_PROTECTED_SECTORS + raidframe.part[candidate].offset; | | 1240 | return RF_PROTECTED_SECTORS + raidframe.part[candidate].offset; |
1239 | } | | 1241 | } |
1240 | #endif | | 1242 | #endif |
1241 | | | 1243 | |
1242 | int | | 1244 | int |
1243 | biosdisk_open(struct open_file *f, ...) | | 1245 | biosdisk_open(struct open_file *f, ...) |
1244 | /* struct open_file *f, int biosdev, int partition */ | | 1246 | /* struct open_file *f, int biosdev, int partition */ |
1245 | { | | 1247 | { |
1246 | va_list ap; | | 1248 | va_list ap; |
1247 | struct biosdisk *d; | | 1249 | struct biosdisk *d; |
1248 | int biosdev; | | 1250 | int biosdev; |
1249 | int partition; | | 1251 | int partition; |
1250 | int error = 0; | | 1252 | int error = 0; |
1251 | | | 1253 | |
1252 | va_start(ap, f); | | 1254 | va_start(ap, f); |
1253 | biosdev = va_arg(ap, int); | | 1255 | biosdev = va_arg(ap, int); |
1254 | d = alloc_biosdisk(biosdev); | | 1256 | d = alloc_biosdisk(biosdev); |
1255 | if (d == NULL) { | | 1257 | if (d == NULL) { |
1256 | error = ENXIO; | | 1258 | error = ENXIO; |
1257 | goto out; | | 1259 | goto out; |
1258 | } | | 1260 | } |
1259 | | | 1261 | |
1260 | partition = va_arg(ap, int); | | 1262 | partition = va_arg(ap, int); |
1261 | bi_disk.biosdev = d->ll.dev; | | 1263 | bi_disk.biosdev = d->ll.dev; |
1262 | bi_disk.partition = partition; | | 1264 | bi_disk.partition = partition; |
1263 | bi_disk.labelsector = -1; | | 1265 | bi_disk.labelsector = -1; |
1264 | | | 1266 | |
1265 | bi_wedge.biosdev = d->ll.dev; | | 1267 | bi_wedge.biosdev = d->ll.dev; |
1266 | bi_wedge.matchblk = -1; | | 1268 | bi_wedge.matchblk = -1; |
1267 | | | 1269 | |
1268 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) | | 1270 | #if !defined(NO_DISKLABEL) || !defined(NO_GPT) |
1269 | error = read_partitions(d, 0, 0); | | 1271 | error = read_partitions(d, 0, 0); |
1270 | if (error == -1) { | | 1272 | if (error == -1) { |
1271 | error = 0; | | 1273 | error = 0; |
1272 | goto nolabel; | | 1274 | goto nolabel; |
1273 | } | | 1275 | } |
1274 | if (error) | | 1276 | if (error) |
1275 | goto out; | | 1277 | goto out; |
1276 | | | 1278 | |
1277 | if (partition >= BIOSDISKNPART || | | 1279 | if (partition >= BIOSDISKNPART || |
1278 | d->part[partition].fstype == FS_UNUSED) { | | 1280 | d->part[partition].fstype == FS_UNUSED) { |
1279 | #ifdef DISK_DEBUG | | 1281 | #ifdef DISK_DEBUG |
1280 | printf("illegal partition\n"); | | 1282 | printf("illegal partition\n"); |
1281 | #endif | | 1283 | #endif |
1282 | error = EPART; | | 1284 | error = EPART; |
1283 | goto out; | | 1285 | goto out; |
1284 | } | | 1286 | } |
1285 | | | 1287 | |
1286 | d->boff = d->part[partition].offset; | | 1288 | d->boff = d->part[partition].offset; |
1287 | | | 1289 | |
1288 | if (d->part[partition].fstype == FS_RAID) | | 1290 | if (d->part[partition].fstype == FS_RAID) |
1289 | #ifndef NO_GPT | | 1291 | #ifndef NO_GPT |
1290 | d->boff += raidframe_part_offset(d, partition); | | 1292 | d->boff += raidframe_part_offset(d, partition); |
1291 | #else | | 1293 | #else |
1292 | d->boff += RF_PROTECTED_SECTORS; | | 1294 | d->boff += RF_PROTECTED_SECTORS; |
1293 | #endif | | 1295 | #endif |
1294 | | | 1296 | |
1295 | #ifdef _STANDALONE | | 1297 | #ifdef _STANDALONE |
1296 | bi_wedge.startblk = d->part[partition].offset; | | 1298 | bi_wedge.startblk = d->part[partition].offset; |
1297 | bi_wedge.nblks = d->part[partition].size; | | 1299 | bi_wedge.nblks = d->part[partition].size; |
1298 | #endif | | 1300 | #endif |
1299 | | | 1301 | |
1300 | nolabel: | | 1302 | nolabel: |
1301 | #endif | | 1303 | #endif |
1302 | #ifdef DISK_DEBUG | | 1304 | #ifdef DISK_DEBUG |
1303 | printf("partition @%"PRId64"\n", d->boff); | | 1305 | printf("partition @%"PRId64"\n", d->boff); |
1304 | #endif | | 1306 | #endif |
1305 | | | 1307 | |
1306 | #ifdef _STANDALONE | | 1308 | #ifdef _STANDALONE |
1307 | add_biosdisk_bootinfo(); | | 1309 | add_biosdisk_bootinfo(); |
1308 | #endif | | 1310 | #endif |
1309 | | | 1311 | |
1310 | f->f_devdata = d; | | 1312 | f->f_devdata = d; |
1311 | out: | | 1313 | out: |
1312 | va_end(ap); | | 1314 | va_end(ap); |
1313 | if (error) | | 1315 | if (error) |
1314 | dealloc_biosdisk(d); | | 1316 | dealloc_biosdisk(d); |
1315 | return error; | | 1317 | return error; |
1316 | } | | 1318 | } |
1317 | | | 1319 | |
1318 | #ifndef NO_GPT | | 1320 | #ifndef NO_GPT |
1319 | static int | | 1321 | static int |
1320 | biosdisk_find_name(const char *fname, int *biosdev, | | 1322 | biosdisk_find_name(const char *fname, int *biosdev, |
1321 | daddr_t *offset, daddr_t *size) | | 1323 | daddr_t *offset, daddr_t *size) |
1322 | { | | 1324 | { |
1323 | struct biosdisk *d; | | 1325 | struct biosdisk *d; |
1324 | char name[MAXDEVNAME + 1]; | | 1326 | char name[MAXDEVNAME + 1]; |
1325 | char *sep; | | 1327 | char *sep; |
1326 | #ifndef NO_RAIDFRAME | | 1328 | #ifndef NO_RAIDFRAME |
1327 | struct raidframe raidframe[RAIDFRAME_NDEV]; | | 1329 | struct raidframe raidframe[RAIDFRAME_NDEV]; |
1328 | int raidframe_count = 0; | | 1330 | int raidframe_count = 0; |
1329 | #endif | | 1331 | #endif |
1330 | int i; | | 1332 | int i; |
1331 | int part; | | 1333 | int part; |
1332 | int ret = -1; | | 1334 | int ret = -1; |
1333 | | | 1335 | |
1334 | /* Strip leadinf NAME= and cut after the coloon included */ | | 1336 | /* Strip leadinf NAME= and cut after the coloon included */ |
1335 | strlcpy(name, fname + 5, MAXDEVNAME); | | 1337 | strlcpy(name, fname + 5, MAXDEVNAME); |
1336 | sep = strchr(name, ':'); | | 1338 | sep = strchr(name, ':'); |
1337 | if (sep) | | 1339 | if (sep) |
1338 | *sep = '\0'; | | 1340 | *sep = '\0'; |
1339 | | | 1341 | |
1340 | for (i = 0; i < MAX_BIOSDISKS; i++) { | | 1342 | for (i = 0; i < MAX_BIOSDISKS; i++) { |
1341 | d = alloc(sizeof(*d)); | | 1343 | d = alloc(sizeof(*d)); |
1342 | if (d == NULL) { | | 1344 | if (d == NULL) { |
1343 | printf("Out of memory\n"); | | 1345 | printf("Out of memory\n"); |
1344 | goto out; | | 1346 | goto out; |
1345 | } | | 1347 | } |
1346 | | | 1348 | |
1347 | memset(d, 0, sizeof(*d)); | | 1349 | memset(d, 0, sizeof(*d)); |
1348 | d->ll.dev = 0x80 + i; /* hd/cd */ | | 1350 | d->ll.dev = 0x80 + i; /* hd/cd */ |
1349 | if (set_geometry(&d->ll, NULL)) | | 1351 | if (set_geometry(&d->ll, NULL)) |
1350 | goto next_disk; | | 1352 | goto next_disk; |
1351 | | | 1353 | |
1352 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 1354 | if (d->ll.type != BIOSDISK_TYPE_HD) |
1353 | goto next_disk; | | 1355 | goto next_disk; |
1354 | | | 1356 | |
1355 | if (read_partitions(d, 0, 0) != 0) | | 1357 | if (read_partitions(d, 0, 0) != 0) |
1356 | goto next_disk; | | 1358 | goto next_disk; |
1357 | | | 1359 | |
1358 | for (part = 0; part < BIOSDISKNPART; part++) { | | 1360 | for (part = 0; part < BIOSDISKNPART; part++) { |
1359 | if (d->part[part].size == 0) | | 1361 | if (d->part[part].size == 0) |
1360 | continue; | | 1362 | continue; |
1361 | if (d->part[part].fstype == FS_UNUSED) | | 1363 | if (d->part[part].fstype == FS_UNUSED) |
1362 | continue; | | 1364 | continue; |
1363 | #ifndef NO_RAIDFRAME | | 1365 | #ifndef NO_RAIDFRAME |
1364 | if (d->part[part].fstype == FS_RAID) { | | 1366 | if (d->part[part].fstype == FS_RAID) { |
1365 | raidframe_probe(raidframe, | | 1367 | raidframe_probe(raidframe, |
1366 | &raidframe_count, d, part); | | 1368 | &raidframe_count, d, part); |
1367 | /* | | 1369 | /* |
1368 | * Do not match RAID partition for a name, | | 1370 | * Do not match RAID partition for a name, |
1369 | * we want to report an inner partition. | | 1371 | * we want to report an inner partition. |
1370 | */ | | 1372 | */ |
1371 | continue; | | 1373 | continue; |
1372 | } | | 1374 | } |
1373 | #endif | | 1375 | #endif |
1374 | if (d->part[part].part_name != NULL && | | 1376 | if (d->part[part].part_name != NULL && |
1375 | strcmp(d->part[part].part_name, name) == 0) { | | 1377 | strcmp(d->part[part].part_name, name) == 0) { |
1376 | *biosdev = d->ll.dev; | | 1378 | *biosdev = d->ll.dev; |
1377 | *offset = d->part[part].offset; | | 1379 | *offset = d->part[part].offset; |
1378 | *size = d->part[part].size; | | 1380 | *size = d->part[part].size; |
1379 | ret = 0; | | 1381 | ret = 0; |
1380 | goto out; | | 1382 | goto out; |
1381 | } | | 1383 | } |
1382 | | | 1384 | |
1383 | } | | 1385 | } |
1384 | next_disk: | | 1386 | next_disk: |
1385 | dealloc_biosdisk(d); | | 1387 | dealloc_biosdisk(d); |
1386 | d = NULL; | | 1388 | d = NULL; |
1387 | } | | 1389 | } |
1388 | | | 1390 | |
1389 | #ifndef NO_RAIDFRAME | | 1391 | #ifndef NO_RAIDFRAME |
1390 | for (i = 0; i < raidframe_count; i++) { | | 1392 | for (i = 0; i < raidframe_count; i++) { |
1391 | int candidate = -1; | | 1393 | int candidate = -1; |
1392 | | | 1394 | |
1393 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { | | 1395 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { |
1394 | printf("Out of memory\n"); | | 1396 | printf("Out of memory\n"); |
1395 | goto out; | | 1397 | goto out; |
1396 | } | | 1398 | } |
1397 | | | 1399 | |
1398 | if (read_partitions(d, | | 1400 | if (read_partitions(d, |
1399 | raidframe[i].offset + RF_PROTECTED_SECTORS, | | 1401 | raidframe[i].offset + RF_PROTECTED_SECTORS, |
1400 | raidframe[i].size) != 0) | | 1402 | raidframe[i].size) != 0) |
1401 | goto next_raidframe; | | 1403 | goto next_raidframe; |
1402 | | | 1404 | |
1403 | for (part = 0; part < BIOSDISKNPART; part++) { | | 1405 | for (part = 0; part < BIOSDISKNPART; part++) { |
1404 | bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; | | 1406 | bool bootme = d->part[part].attr & GPT_ENT_ATTR_BOOTME; |
1405 | if (d->part[part].size == 0) | | 1407 | if (d->part[part].size == 0) |
1406 | continue; | | 1408 | continue; |
1407 | if (d->part[part].fstype == FS_UNUSED) | | 1409 | if (d->part[part].fstype == FS_UNUSED) |
1408 | continue; | | 1410 | continue; |
1409 | | | 1411 | |
1410 | if (d->part[part].part_name != NULL && | | 1412 | if (d->part[part].part_name != NULL && |
1411 | strcmp(d->part[part].part_name, name) == 0) { | | 1413 | strcmp(d->part[part].part_name, name) == 0) { |
1412 | *biosdev = raidframe[i].biosdev; | | 1414 | *biosdev = raidframe[i].biosdev; |
1413 | *offset = raidframe[i].offset | | 1415 | *offset = raidframe[i].offset |
1414 | + RF_PROTECTED_SECTORS | | 1416 | + RF_PROTECTED_SECTORS |
1415 | + d->part[part].offset; | | 1417 | + d->part[part].offset; |
1416 | *size = d->part[part].size; | | 1418 | *size = d->part[part].size; |
1417 | ret = 0; | | 1419 | ret = 0; |
1418 | goto out; | | 1420 | goto out; |
1419 | } | | 1421 | } |
1420 | if (strcmp(raidframe[i].parent_name, name) == 0) { | | 1422 | if (strcmp(raidframe[i].parent_name, name) == 0) { |
1421 | if (candidate == -1 || bootme) | | 1423 | if (candidate == -1 || bootme) |
1422 | candidate = part; | | 1424 | candidate = part; |
1423 | continue; | | 1425 | continue; |
1424 | } | | 1426 | } |
1425 | } | | 1427 | } |
1426 | | | 1428 | |
1427 | if (candidate != -1) { | | 1429 | if (candidate != -1) { |
1428 | *biosdev = raidframe[i].biosdev; | | 1430 | *biosdev = raidframe[i].biosdev; |
1429 | *offset = raidframe[i].offset | | 1431 | *offset = raidframe[i].offset |
1430 | + RF_PROTECTED_SECTORS | | 1432 | + RF_PROTECTED_SECTORS |
1431 | + d->part[candidate].offset; | | 1433 | + d->part[candidate].offset; |
1432 | *size = d->part[candidate].size; | | 1434 | *size = d->part[candidate].size; |
1433 | ret = 0; | | 1435 | ret = 0; |
1434 | goto out; | | 1436 | goto out; |
1435 | } | | 1437 | } |
1436 | | | 1438 | |
1437 | next_raidframe: | | 1439 | next_raidframe: |
1438 | dealloc_biosdisk(d); | | 1440 | dealloc_biosdisk(d); |
1439 | d = NULL; | | 1441 | d = NULL; |
1440 | } | | 1442 | } |
1441 | #endif | | 1443 | #endif |
1442 | | | 1444 | |
1443 | out: | | 1445 | out: |
1444 | if (d != NULL) | | 1446 | if (d != NULL) |
1445 | dealloc_biosdisk(d); | | 1447 | dealloc_biosdisk(d); |
1446 | | | 1448 | |
1447 | return ret; | | 1449 | return ret; |
1448 | } | | 1450 | } |
1449 | #endif | | 1451 | #endif |
1450 | | | 1452 | |
1451 | #ifndef NO_RAIDFRAME | | 1453 | #ifndef NO_RAIDFRAME |
1452 | static int | | 1454 | static int |
1453 | biosdisk_find_raid(const char *name, int *biosdev, | | 1455 | biosdisk_find_raid(const char *name, int *biosdev, |
1454 | daddr_t *offset, daddr_t *size) | | 1456 | daddr_t *offset, daddr_t *size) |
1455 | { | | 1457 | { |
1456 | struct biosdisk *d = NULL; | | 1458 | struct biosdisk *d = NULL; |
1457 | struct raidframe raidframe[RAIDFRAME_NDEV]; | | 1459 | struct raidframe raidframe[RAIDFRAME_NDEV]; |
1458 | int raidframe_count = 0; | | 1460 | int raidframe_count = 0; |
1459 | int i; | | 1461 | int i; |
1460 | int target_unit = 0; | | 1462 | int target_unit = 0; |
1461 | int target_part; | | 1463 | int target_part; |
1462 | int part; | | 1464 | int part; |
1463 | int ret = -1; | | 1465 | int ret = -1; |
1464 | | | 1466 | |
1465 | if (strstr(name, "raid") != name) | | 1467 | if (strstr(name, "raid") != name) |
1466 | goto out; | | 1468 | goto out; |
1467 | | | 1469 | |
1468 | #define isnum(c) ((c) >= '0' && (c) <= '9') | | 1470 | #define isnum(c) ((c) >= '0' && (c) <= '9') |
1469 | i = 4; /* skip leading "raid" */ | | 1471 | i = 4; /* skip leading "raid" */ |
1470 | if (!isnum(name[i])) | | 1472 | if (!isnum(name[i])) |
1471 | goto out; | | 1473 | goto out; |
1472 | do { | | 1474 | do { |
1473 | target_unit *= 10; | | 1475 | target_unit *= 10; |
1474 | target_unit += name[i++] - '0'; | | 1476 | target_unit += name[i++] - '0'; |
1475 | } while (isnum(name[i])); | | 1477 | } while (isnum(name[i])); |
1476 | | | 1478 | |
1477 | #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') | | 1479 | #define isvalidpart(c) ((c) >= 'a' && (c) <= 'z') |
1478 | | | 1480 | |
1479 | if (!isvalidpart(name[i])) | | 1481 | if (!isvalidpart(name[i])) |
1480 | goto out; | | 1482 | goto out; |
1481 | target_part = name[i] - 'a'; | | 1483 | target_part = name[i] - 'a'; |
1482 | | | 1484 | |
1483 | for (i = 0; i < MAX_BIOSDISKS; i++) { | | 1485 | for (i = 0; i < MAX_BIOSDISKS; i++) { |
1484 | d = alloc(sizeof(*d)); | | 1486 | d = alloc(sizeof(*d)); |
1485 | if (d == NULL) { | | 1487 | if (d == NULL) { |
1486 | printf("Out of memory\n"); | | 1488 | printf("Out of memory\n"); |
1487 | goto out; | | 1489 | goto out; |
1488 | } | | 1490 | } |
1489 | | | 1491 | |
1490 | memset(d, 0, sizeof(*d)); | | 1492 | memset(d, 0, sizeof(*d)); |
1491 | d->ll.dev = 0x80 + i; /* hd/cd */ | | 1493 | d->ll.dev = 0x80 + i; /* hd/cd */ |
1492 | if (set_geometry(&d->ll, NULL)) | | 1494 | if (set_geometry(&d->ll, NULL)) |
1493 | goto next_disk; | | 1495 | goto next_disk; |
1494 | | | 1496 | |
1495 | if (d->ll.type != BIOSDISK_TYPE_HD) | | 1497 | if (d->ll.type != BIOSDISK_TYPE_HD) |
1496 | goto next_disk; | | 1498 | goto next_disk; |
1497 | | | 1499 | |
1498 | if (read_partitions(d, 0, 0) != 0) | | 1500 | if (read_partitions(d, 0, 0) != 0) |
1499 | goto next_disk; | | 1501 | goto next_disk; |
1500 | | | 1502 | |
1501 | for (part = 0; part < BIOSDISKNPART; part++) { | | 1503 | for (part = 0; part < BIOSDISKNPART; part++) { |
1502 | if (d->part[part].size == 0) | | 1504 | if (d->part[part].size == 0) |
1503 | continue; | | 1505 | continue; |
1504 | if (d->part[part].fstype != FS_RAID) | | 1506 | if (d->part[part].fstype != FS_RAID) |
1505 | continue; | | 1507 | continue; |
1506 | raidframe_probe(raidframe, | | 1508 | raidframe_probe(raidframe, |
1507 | &raidframe_count, d, part); | | 1509 | &raidframe_count, d, part); |
1508 | | | 1510 | |
1509 | } | | 1511 | } |
1510 | next_disk: | | 1512 | next_disk: |
1511 | dealloc_biosdisk(d); | | 1513 | dealloc_biosdisk(d); |
1512 | d = NULL; | | 1514 | d = NULL; |
1513 | } | | 1515 | } |
1514 | | | 1516 | |
1515 | for (i = 0; i < raidframe_count; i++) { | | 1517 | for (i = 0; i < raidframe_count; i++) { |
1516 | if (raidframe[i].last_unit != target_unit) | | 1518 | if (raidframe[i].last_unit != target_unit) |
1517 | continue; | | 1519 | continue; |
1518 | | | 1520 | |
1519 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { | | 1521 | if ((d = alloc_biosdisk(raidframe[i].biosdev)) == NULL) { |
1520 | printf("Out of memory\n"); | | 1522 | printf("Out of memory\n"); |
1521 | goto out; | | 1523 | goto out; |
1522 | } | | 1524 | } |
1523 | | | 1525 | |
1524 | if (read_partitions(d, | | 1526 | if (read_partitions(d, |
1525 | raidframe[i].offset + RF_PROTECTED_SECTORS, | | 1527 | raidframe[i].offset + RF_PROTECTED_SECTORS, |
1526 | raidframe[i].size) != 0) | | 1528 | raidframe[i].size) != 0) |
1527 | goto next_raidframe; | | 1529 | goto next_raidframe; |
1528 | | | 1530 | |
1529 | for (part = 0; part < BIOSDISKNPART; part++) { | | 1531 | for (part = 0; part < BIOSDISKNPART; part++) { |
1530 | if (d->part[part].size == 0) | | 1532 | if (d->part[part].size == 0) |
1531 | continue; | | 1533 | continue; |
1532 | if (d->part[part].fstype == FS_UNUSED) | | 1534 | if (d->part[part].fstype == FS_UNUSED) |
1533 | continue; | | 1535 | continue; |
1534 | if (part == target_part) { | | 1536 | if (part == target_part) { |
1535 | *biosdev = raidframe[i].biosdev; | | 1537 | *biosdev = raidframe[i].biosdev; |
1536 | *offset = raidframe[i].offset | | 1538 | *offset = raidframe[i].offset |
1537 | + RF_PROTECTED_SECTORS | | 1539 | + RF_PROTECTED_SECTORS |
1538 | + d->part[part].offset; | | 1540 | + d->part[part].offset; |
1539 | *size = d->part[part].size; | | 1541 | *size = d->part[part].size; |
1540 | ret = 0; | | 1542 | ret = 0; |
1541 | goto out; | | 1543 | goto out; |
1542 | } | | 1544 | } |
1543 | } | | 1545 | } |
1544 | next_raidframe: | | 1546 | next_raidframe: |
1545 | dealloc_biosdisk(d); | | 1547 | dealloc_biosdisk(d); |
1546 | d = NULL; | | 1548 | d = NULL; |
1547 | } | | 1549 | } |
1548 | out: | | 1550 | out: |
1549 | if (d != NULL) | | 1551 | if (d != NULL) |
1550 | dealloc_biosdisk(d); | | 1552 | dealloc_biosdisk(d); |
1551 | | | 1553 | |
1552 | return ret; | | 1554 | return ret; |
1553 | } | | 1555 | } |
1554 | #endif | | 1556 | #endif |
1555 | | | 1557 | |
1556 | int | | 1558 | int |
1557 | biosdisk_open_name(struct open_file *f, const char *name) | | 1559 | biosdisk_open_name(struct open_file *f, const char *name) |
1558 | { | | 1560 | { |
1559 | #if defined(NO_GPT) && defined(NO_RAIDFRAME) | | 1561 | #if defined(NO_GPT) && defined(NO_RAIDFRAME) |
1560 | return ENXIO; | | 1562 | return ENXIO; |
1561 | #else | | 1563 | #else |
1562 | struct biosdisk *d = NULL; | | 1564 | struct biosdisk *d = NULL; |
1563 | int biosdev; | | 1565 | int biosdev; |
1564 | daddr_t offset; | | 1566 | daddr_t offset; |
1565 | daddr_t size; | | 1567 | daddr_t size; |
1566 | int error = -1; | | 1568 | int error = -1; |
1567 | | | 1569 | |
1568 | #ifndef NO_GPT | | 1570 | #ifndef NO_GPT |
1569 | if (strstr(name, "NAME=") == name) | | 1571 | if (strstr(name, "NAME=") == name) |
1570 | error = biosdisk_find_name(name, &biosdev, &offset, &size); | | 1572 | error = biosdisk_find_name(name, &biosdev, &offset, &size); |
1571 | #endif | | 1573 | #endif |
1572 | #ifndef NO_RAIDFRAME | | 1574 | #ifndef NO_RAIDFRAME |
1573 | if (strstr(name, "raid") == name) | | 1575 | if (strstr(name, "raid") == name) |
1574 | error = biosdisk_find_raid(name, &biosdev, &offset, &size); | | 1576 | error = biosdisk_find_raid(name, &biosdev, &offset, &size); |
1575 | #endif | | 1577 | #endif |
1576 | | | 1578 | |
1577 | if (error != 0) { | | 1579 | if (error != 0) { |
1578 | printf("%s not found\n", name); | | 1580 | printf("%s not found\n", name); |
1579 | error = ENXIO; | | 1581 | error = ENXIO; |
1580 | goto out; | | 1582 | goto out; |
1581 | } | | 1583 | } |
1582 | | | 1584 | |
1583 | d = alloc_biosdisk(biosdev); | | 1585 | d = alloc_biosdisk(biosdev); |
1584 | if (d == NULL) { | | 1586 | if (d == NULL) { |
1585 | error = ENXIO; | | 1587 | error = ENXIO; |
1586 | goto out; | | 1588 | goto out; |
1587 | } | | 1589 | } |
1588 | | | 1590 | |
1589 | bi_disk.biosdev = d->ll.dev; | | 1591 | bi_disk.biosdev = d->ll.dev; |
1590 | bi_disk.partition = 0; | | 1592 | bi_disk.partition = 0; |
1591 | bi_disk.labelsector = -1; | | 1593 | bi_disk.labelsector = -1; |
1592 | | | 1594 | |
1593 | bi_wedge.biosdev = d->ll.dev; | | 1595 | bi_wedge.biosdev = d->ll.dev; |
1594 | | | 1596 | |
1595 | /* | | 1597 | /* |
1596 | * If we did not get wedge match info from check_gpt() | | 1598 | * If we did not get wedge match info from check_gpt() |
1597 | * compute it now. | | 1599 | * compute it now. |
1598 | */ | | 1600 | */ |
1599 | if (bi_wedge.matchblk == -1) { | | 1601 | if (bi_wedge.matchblk == -1) { |
1600 | if (readsects(&d->ll, offset, 1, d->buf, 1)) { | | 1602 | if (readsects(&d->ll, offset, 1, d->buf, 1)) { |
1601 | #ifdef DISK_DEBUG | | 1603 | #ifdef DISK_DEBUG |
1602 | printf("Error reading sector at %"PRId64"\n", offset); | | 1604 | printf("Error reading sector at %"PRId64"\n", offset); |
1603 | #endif | | 1605 | #endif |
1604 | error = EIO; | | 1606 | error = EIO; |
1605 | goto out; | | 1607 | goto out; |
1606 | } | | 1608 | } |
1607 | | | 1609 | |
1608 | bi_wedge.matchblk = offset; | | 1610 | bi_wedge.matchblk = offset; |
1609 | bi_wedge.matchnblks = 1; | | 1611 | bi_wedge.matchnblks = 1; |
1610 | | | 1612 | |
1611 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); | | 1613 | md5(bi_wedge.matchhash, d->buf, d->ll.secsize); |
1612 | } | | 1614 | } |
1613 | | | 1615 | |
1614 | d->boff = offset; | | 1616 | d->boff = offset; |
1615 | | | 1617 | |
1616 | bi_wedge.startblk = offset; | | 1618 | bi_wedge.startblk = offset; |
1617 | bi_wedge.nblks = size; | | 1619 | bi_wedge.nblks = size; |
1618 | | | 1620 | |
1619 | #ifdef _STANDALONE | | 1621 | #ifdef _STANDALONE |
1620 | add_biosdisk_bootinfo(); | | 1622 | add_biosdisk_bootinfo(); |
1621 | #endif | | 1623 | #endif |
1622 | | | 1624 | |
1623 | f->f_devdata = d; | | 1625 | f->f_devdata = d; |
1624 | out: | | 1626 | out: |
1625 | if (error && d != NULL) | | 1627 | if (error && d != NULL) |
1626 | dealloc_biosdisk(d); | | 1628 | dealloc_biosdisk(d); |
1627 | return error; | | 1629 | return error; |
1628 | #endif | | 1630 | #endif |
1629 | } | | 1631 | } |
1630 | | | 1632 | |
1631 | | | 1633 | |
1632 | | | 1634 | |
1633 | #ifndef LIBSA_NO_FS_CLOSE | | 1635 | #ifndef LIBSA_NO_FS_CLOSE |
1634 | int | | 1636 | int |
1635 | biosdisk_close(struct open_file *f) | | 1637 | biosdisk_close(struct open_file *f) |
1636 | { | | 1638 | { |
1637 | struct biosdisk *d = f->f_devdata; | | 1639 | struct biosdisk *d = f->f_devdata; |
1638 | | | 1640 | |
1639 | /* let the floppy drive go off */ | | 1641 | /* let the floppy drive go off */ |
1640 | if (d->ll.type == BIOSDISK_TYPE_FD) | | 1642 | if (d->ll.type == BIOSDISK_TYPE_FD) |
1641 | wait_sec(3); /* 2s is enough on all PCs I found */ | | 1643 | wait_sec(3); /* 2s is enough on all PCs I found */ |
1642 | | | 1644 | |
1643 | dealloc_biosdisk(d); | | 1645 | dealloc_biosdisk(d); |
1644 | f->f_devdata = NULL; | | 1646 | f->f_devdata = NULL; |
1645 | return 0; | | 1647 | return 0; |
1646 | } | | 1648 | } |
1647 | #endif | | 1649 | #endif |
1648 | | | 1650 | |
1649 | int | | 1651 | int |
1650 | biosdisk_ioctl(struct open_file *f, u_long cmd, void *arg) | | 1652 | biosdisk_ioctl(struct open_file *f, u_long cmd, void *arg) |
1651 | { | | 1653 | { |
1652 | return EIO; | | 1654 | return EIO; |
1653 | } | | 1655 | } |