xref: /illumos-gate/usr/src/cmd/fs.d/pcfs/common/pcfs_common.c (revision fdc43e978a96b43e8b78e80d9bc6f39c99a8ca83)
1*fdc43e97SToomas Soome /*
2*fdc43e97SToomas Soome  * CDDL HEADER START
3*fdc43e97SToomas Soome  *
4*fdc43e97SToomas Soome  * The contents of this file are subject to the terms of the
5*fdc43e97SToomas Soome  * Common Development and Distribution License (the "License").
6*fdc43e97SToomas Soome  * You may not use this file except in compliance with the License.
7*fdc43e97SToomas Soome  *
8*fdc43e97SToomas Soome  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fdc43e97SToomas Soome  * or http://www.opensolaris.org/os/licensing.
10*fdc43e97SToomas Soome  * See the License for the specific language governing permissions
11*fdc43e97SToomas Soome  * and limitations under the License.
12*fdc43e97SToomas Soome  *
13*fdc43e97SToomas Soome  * When distributing Covered Code, include this CDDL HEADER in each
14*fdc43e97SToomas Soome  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fdc43e97SToomas Soome  * If applicable, add the following below this CDDL HEADER, with the
16*fdc43e97SToomas Soome  * fields enclosed by brackets "[]" replaced with your own identifying
17*fdc43e97SToomas Soome  * information: Portions Copyright [yyyy] [name of copyright owner]
18*fdc43e97SToomas Soome  *
19*fdc43e97SToomas Soome  * CDDL HEADER END
20*fdc43e97SToomas Soome  */
21*fdc43e97SToomas Soome /*
22*fdc43e97SToomas Soome  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23*fdc43e97SToomas Soome  * Use is subject to license terms.
24*fdc43e97SToomas Soome  * Copyright (c) 2011 Gary Mills
25*fdc43e97SToomas Soome  * Copyright 2024 MNX Cloud, Inc.
26*fdc43e97SToomas Soome  */
27*fdc43e97SToomas Soome 
28*fdc43e97SToomas Soome /*
29*fdc43e97SToomas Soome  * common functions used by pcfs tools.
30*fdc43e97SToomas Soome  */
31*fdc43e97SToomas Soome #include <stdio.h>
32*fdc43e97SToomas Soome #include <string.h>
33*fdc43e97SToomas Soome #include <errno.h>
34*fdc43e97SToomas Soome #include <err.h>
35*fdc43e97SToomas Soome #include <unistd.h>
36*fdc43e97SToomas Soome #include <stdlib.h>
37*fdc43e97SToomas Soome #include <libintl.h>
38*fdc43e97SToomas Soome #include <locale.h>
39*fdc43e97SToomas Soome #include <langinfo.h>
40*fdc43e97SToomas Soome #include <regex.h>
41*fdc43e97SToomas Soome #include <sys/isa_defs.h>
42*fdc43e97SToomas Soome #include <sys/types.h>
43*fdc43e97SToomas Soome #include <sys/stat.h>
44*fdc43e97SToomas Soome #include <sys/fcntl.h>
45*fdc43e97SToomas Soome #include <sys/dktp/fdisk.h>
46*fdc43e97SToomas Soome #include <sys/dkio.h>
47*fdc43e97SToomas Soome #include <sys/fs/pc_fs.h>
48*fdc43e97SToomas Soome #include <sys/fs/pc_dir.h>
49*fdc43e97SToomas Soome #include <sys/fs/pc_label.h>
50*fdc43e97SToomas Soome #include "pcfs_common.h"
51*fdc43e97SToomas Soome #include "pcfs_bpb.h"
52*fdc43e97SToomas Soome 
53*fdc43e97SToomas Soome /*
54*fdc43e97SToomas Soome  *	The assumption here is that _BIG_ENDIAN implies sparc, and
55*fdc43e97SToomas Soome  *	so in addition to swapping bytes we also have to construct
56*fdc43e97SToomas Soome  *	packed structures by hand to avoid bus errors due to improperly
57*fdc43e97SToomas Soome  *	aligned pointers.
58*fdc43e97SToomas Soome  */
59*fdc43e97SToomas Soome #ifdef _BIG_ENDIAN
60*fdc43e97SToomas Soome void swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp);
61*fdc43e97SToomas Soome void swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp);
62*fdc43e97SToomas Soome #endif /* _BIG_ENDIAN */
63*fdc43e97SToomas Soome 
64*fdc43e97SToomas Soome /*
65*fdc43e97SToomas Soome  * Validate sector size.
66*fdc43e97SToomas Soome  */
67*fdc43e97SToomas Soome bool
is_sector_size_valid(size_t size)68*fdc43e97SToomas Soome is_sector_size_valid(size_t size)
69*fdc43e97SToomas Soome {
70*fdc43e97SToomas Soome 	if (size != 512 && size != 1024 && size != 2048 && size != 4096)
71*fdc43e97SToomas Soome 		return (false);
72*fdc43e97SToomas Soome 	return (true);
73*fdc43e97SToomas Soome }
74*fdc43e97SToomas Soome 
75*fdc43e97SToomas Soome /*
76*fdc43e97SToomas Soome  * Use DKIOCGMEDIAINFO to get sector size.
77*fdc43e97SToomas Soome  */
78*fdc43e97SToomas Soome int
get_media_sector_size(int fd,size_t * sizep)79*fdc43e97SToomas Soome get_media_sector_size(int fd, size_t *sizep)
80*fdc43e97SToomas Soome {
81*fdc43e97SToomas Soome 	struct dk_minfo dkminfo;
82*fdc43e97SToomas Soome 
83*fdc43e97SToomas Soome 	if (ioctl(fd, DKIOCGMEDIAINFO, &dkminfo) != -1) {
84*fdc43e97SToomas Soome 		*sizep = dkminfo.dki_lbsize;
85*fdc43e97SToomas Soome 		return (0);
86*fdc43e97SToomas Soome 	}
87*fdc43e97SToomas Soome 	/* In case the DKIOCGMEDIAINFO is not supported, return MINBPS. */
88*fdc43e97SToomas Soome 	if (errno == ENOTTY) {
89*fdc43e97SToomas Soome 		*sizep = MINBPS;
90*fdc43e97SToomas Soome 		return (0);
91*fdc43e97SToomas Soome 	}
92*fdc43e97SToomas Soome 
93*fdc43e97SToomas Soome 	return (errno);
94*fdc43e97SToomas Soome }
95*fdc43e97SToomas Soome 
96*fdc43e97SToomas Soome /*
97*fdc43e97SToomas Soome  * store_16_bits
98*fdc43e97SToomas Soome  *	Save the lower 16 bits of a 32 bit value (v) into the provided
99*fdc43e97SToomas Soome  *	buffer (pointed at by *bp), and increment the buffer pointer
100*fdc43e97SToomas Soome  *	as well.  This way the routine can be called multiple times in
101*fdc43e97SToomas Soome  *	succession to fill buffers.  The value is stored in little-endian
102*fdc43e97SToomas Soome  *	order.
103*fdc43e97SToomas Soome  */
104*fdc43e97SToomas Soome void
store_16_bits(uchar_t ** bp,uint32_t v)105*fdc43e97SToomas Soome store_16_bits(uchar_t **bp, uint32_t v)
106*fdc43e97SToomas Soome {
107*fdc43e97SToomas Soome 	uchar_t *l = *bp;
108*fdc43e97SToomas Soome 
109*fdc43e97SToomas Soome 	*l++ = v & 0xff;
110*fdc43e97SToomas Soome 	*l = (v >> 8) & 0xff;
111*fdc43e97SToomas Soome 	*bp += 2;
112*fdc43e97SToomas Soome }
113*fdc43e97SToomas Soome 
114*fdc43e97SToomas Soome void
read_16_bits(uchar_t * bp,uint32_t * value)115*fdc43e97SToomas Soome read_16_bits(uchar_t *bp, uint32_t *value)
116*fdc43e97SToomas Soome {
117*fdc43e97SToomas Soome 	*value = *bp++;
118*fdc43e97SToomas Soome 	*value += *bp << 8;
119*fdc43e97SToomas Soome }
120*fdc43e97SToomas Soome 
121*fdc43e97SToomas Soome /*
122*fdc43e97SToomas Soome  * store_32_bits
123*fdc43e97SToomas Soome  *	Save the 32 bit value (v) into the provided buffer (pointed
124*fdc43e97SToomas Soome  *	at by *bp), and increment the buffer pointer as well.  This way
125*fdc43e97SToomas Soome  *	the routine can be called multiple times in succession to fill
126*fdc43e97SToomas Soome  *	buffers.  The value is stored in little-endian order.
127*fdc43e97SToomas Soome  */
128*fdc43e97SToomas Soome void
store_32_bits(uchar_t ** bp,uint32_t v)129*fdc43e97SToomas Soome store_32_bits(uchar_t **bp, uint32_t v)
130*fdc43e97SToomas Soome {
131*fdc43e97SToomas Soome 	uchar_t *l = *bp;
132*fdc43e97SToomas Soome 	int b;
133*fdc43e97SToomas Soome 
134*fdc43e97SToomas Soome 	for (b = 0; b < 4; b++) {
135*fdc43e97SToomas Soome 		*l++ = v & 0xff;
136*fdc43e97SToomas Soome 		v = v >> 8;
137*fdc43e97SToomas Soome 	}
138*fdc43e97SToomas Soome 	*bp += 4;
139*fdc43e97SToomas Soome }
140*fdc43e97SToomas Soome 
141*fdc43e97SToomas Soome void
read_32_bits(uchar_t * bp,uint32_t * value)142*fdc43e97SToomas Soome read_32_bits(uchar_t *bp, uint32_t *value)
143*fdc43e97SToomas Soome {
144*fdc43e97SToomas Soome 	*value = *bp++;
145*fdc43e97SToomas Soome 	*value += *bp++ << 8;
146*fdc43e97SToomas Soome 	*value += *bp++ << 16;
147*fdc43e97SToomas Soome 	*value += *bp++ << 24;
148*fdc43e97SToomas Soome }
149*fdc43e97SToomas Soome 
150*fdc43e97SToomas Soome /*
151*fdc43e97SToomas Soome  *  dump_bytes  -- display bytes as hex numbers.
152*fdc43e97SToomas Soome  *		   b is the pointer to the byte buffer
153*fdc43e97SToomas Soome  *		   n is the number of bytes in the buffer
154*fdc43e97SToomas Soome  */
155*fdc43e97SToomas Soome /* Note: BPL = bytes to display per line */
156*fdc43e97SToomas Soome #define	BPL 16
157*fdc43e97SToomas Soome 
158*fdc43e97SToomas Soome void
dump_bytes(uchar_t * buf,int n)159*fdc43e97SToomas Soome dump_bytes(uchar_t *buf, int n)
160*fdc43e97SToomas Soome {
161*fdc43e97SToomas Soome 	int printedCount;
162*fdc43e97SToomas Soome 	int countdown = n;
163*fdc43e97SToomas Soome 	int countup = 0;
164*fdc43e97SToomas Soome 	int offset = 0;
165*fdc43e97SToomas Soome 	int byte;
166*fdc43e97SToomas Soome 
167*fdc43e97SToomas Soome 	/* Display offset, 16 bytes per line, and printable ascii version */
168*fdc43e97SToomas Soome 	while (countdown > 0) {
169*fdc43e97SToomas Soome 		printedCount = 0;
170*fdc43e97SToomas Soome 		(void) fprintf(stderr, "\n%06x: ", offset);
171*fdc43e97SToomas Soome 		/*
172*fdc43e97SToomas Soome 		 * Print Hex value of characters in columns on left
173*fdc43e97SToomas Soome 		 */
174*fdc43e97SToomas Soome 		for (byte = 0; byte < BPL; byte++) {
175*fdc43e97SToomas Soome 			if (countup + byte < n) {
176*fdc43e97SToomas Soome 				(void) fprintf(stderr,
177*fdc43e97SToomas Soome 				    "%02x ", (buf[countup + byte] & 0xff));
178*fdc43e97SToomas Soome 				printedCount++;
179*fdc43e97SToomas Soome 			} else {
180*fdc43e97SToomas Soome 				(void) fprintf(stderr, "   ");
181*fdc43e97SToomas Soome 			}
182*fdc43e97SToomas Soome 		}
183*fdc43e97SToomas Soome 		/*
184*fdc43e97SToomas Soome 		 * Right side has the printable character or '.' for
185*fdc43e97SToomas Soome 		 * unprintable for each column of the left.
186*fdc43e97SToomas Soome 		 */
187*fdc43e97SToomas Soome 		for (byte = 0; byte < BPL; byte++) {
188*fdc43e97SToomas Soome 			if ((countup + byte < n) &&
189*fdc43e97SToomas Soome 			    ((buf[countup + byte] >= ' ') &&
190*fdc43e97SToomas Soome 			    (buf[countup + byte] <= '~'))) {
191*fdc43e97SToomas Soome 				(void) fprintf(stderr, "%c",
192*fdc43e97SToomas Soome 				    buf[countup + byte]);
193*fdc43e97SToomas Soome 			} else {
194*fdc43e97SToomas Soome 				(void) fprintf(stderr, ".");
195*fdc43e97SToomas Soome 			}
196*fdc43e97SToomas Soome 		}
197*fdc43e97SToomas Soome 		countup += printedCount;
198*fdc43e97SToomas Soome 		offset += printedCount;
199*fdc43e97SToomas Soome 		countdown -= printedCount;
200*fdc43e97SToomas Soome 	}
201*fdc43e97SToomas Soome 	(void) fprintf(stderr, "\n\n");
202*fdc43e97SToomas Soome }
203*fdc43e97SToomas Soome 
204*fdc43e97SToomas Soome /*
205*fdc43e97SToomas Soome  *  header_for_dump  --  display simple header over what will be output.
206*fdc43e97SToomas Soome  */
207*fdc43e97SToomas Soome void
header_for_dump(void)208*fdc43e97SToomas Soome header_for_dump(void)
209*fdc43e97SToomas Soome {
210*fdc43e97SToomas Soome 	int byte;
211*fdc43e97SToomas Soome 
212*fdc43e97SToomas Soome 	(void) fprintf(stderr, "\n        ");
213*fdc43e97SToomas Soome 	for (byte = 0; byte < BPL; byte++)
214*fdc43e97SToomas Soome 		(void) fprintf(stderr, "%02x ", byte);
215*fdc43e97SToomas Soome 	(void) fprintf(stderr, "\n       ");
216*fdc43e97SToomas Soome 	byte = 3 * BPL;
217*fdc43e97SToomas Soome 	while (byte-- > 0)
218*fdc43e97SToomas Soome 		(void) fprintf(stderr, "-");
219*fdc43e97SToomas Soome }
220*fdc43e97SToomas Soome 
221*fdc43e97SToomas Soome /*
222*fdc43e97SToomas Soome  *  We are basically (incorrectly) assuming that if you aren't running
223*fdc43e97SToomas Soome  *  on x86 the BPB has to be packed by hand AND that the bytes must
224*fdc43e97SToomas Soome  *  be swapped.  One or both of these assumptions may one day be invalid.
225*fdc43e97SToomas Soome  *  (if they aren't already :-))
226*fdc43e97SToomas Soome  */
227*fdc43e97SToomas Soome #ifdef _BIG_ENDIAN
228*fdc43e97SToomas Soome /*
229*fdc43e97SToomas Soome  *  swap_pack_grab{32}bpb
230*fdc43e97SToomas Soome  *	If not on an x86 we assume the structures making up the bpb
231*fdc43e97SToomas Soome  *	were not packed and that longs and shorts need to be byte swapped
232*fdc43e97SToomas Soome  *	(we've kept everything in host order up until now).  A new architecture
233*fdc43e97SToomas Soome  *	might not need to swap or might not need to pack, in which case
234*fdc43e97SToomas Soome  *	new routines will have to be written.  Of course if an architecture
235*fdc43e97SToomas Soome  *	supports both packing and little-endian host order, it can follow the
236*fdc43e97SToomas Soome  *	same path as the x86 code.
237*fdc43e97SToomas Soome  */
238*fdc43e97SToomas Soome void
swap_pack_grabbpb(bpb_t * wbpb,struct _boot_sector * bsp)239*fdc43e97SToomas Soome swap_pack_grabbpb(bpb_t *wbpb, struct _boot_sector *bsp)
240*fdc43e97SToomas Soome {
241*fdc43e97SToomas Soome 	uchar_t *grabp;
242*fdc43e97SToomas Soome 
243*fdc43e97SToomas Soome 	grabp = (uchar_t *)&(bsp->bs_filler[ORIG_BPB_START_INDEX]);
244*fdc43e97SToomas Soome 
245*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.bytes_per_sector))[1] = *grabp++;
246*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.bytes_per_sector))[0] = *grabp++;
247*fdc43e97SToomas Soome 	wbpb->bpb.sectors_per_cluster = *grabp++;
248*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.resv_sectors))[1] = *grabp++;
249*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.resv_sectors))[0] = *grabp++;
250*fdc43e97SToomas Soome 	wbpb->bpb.num_fats = *grabp++;
251*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.num_root_entries))[1] = *grabp++;
252*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.num_root_entries))[0] = *grabp++;
253*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_volume))[1] = *grabp++;
254*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_volume))[0] = *grabp++;
255*fdc43e97SToomas Soome 	wbpb->bpb.media = *grabp++;
256*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_per_fat))[1] = *grabp++;
257*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_per_fat))[0] = *grabp++;
258*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_per_track))[1] = *grabp++;
259*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_per_track))[0] = *grabp++;
260*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.heads))[1] = *grabp++;
261*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.heads))[0] = *grabp++;
262*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.hidden_sectors))[3] = *grabp++;
263*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.hidden_sectors))[2] = *grabp++;
264*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.hidden_sectors))[1] = *grabp++;
265*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.hidden_sectors))[0] = *grabp++;
266*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[3] = *grabp++;
267*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[2] = *grabp++;
268*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[1] = *grabp++;
269*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb.sectors_in_logical_volume))[0] = *grabp++;
270*fdc43e97SToomas Soome 	wbpb->ebpb.phys_drive_num = *grabp++;
271*fdc43e97SToomas Soome 	wbpb->ebpb.reserved = *grabp++;
272*fdc43e97SToomas Soome 	wbpb->ebpb.ext_signature = *grabp++;
273*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->ebpb.volume_id))[3] = *grabp++;
274*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->ebpb.volume_id))[2] = *grabp++;
275*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->ebpb.volume_id))[1] = *grabp++;
276*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->ebpb.volume_id))[0] = *grabp++;
277*fdc43e97SToomas Soome 
278*fdc43e97SToomas Soome 	(void) strncpy((char *)wbpb->ebpb.volume_label, (char *)grabp, 11);
279*fdc43e97SToomas Soome 	grabp += 11;
280*fdc43e97SToomas Soome 	(void) strncpy((char *)wbpb->ebpb.type, (char *)grabp, 8);
281*fdc43e97SToomas Soome }
282*fdc43e97SToomas Soome 
283*fdc43e97SToomas Soome void
swap_pack_grab32bpb(bpb_t * wbpb,struct _boot_sector * bsp)284*fdc43e97SToomas Soome swap_pack_grab32bpb(bpb_t *wbpb, struct _boot_sector *bsp)
285*fdc43e97SToomas Soome {
286*fdc43e97SToomas Soome 	uchar_t *grabp;
287*fdc43e97SToomas Soome 
288*fdc43e97SToomas Soome 	grabp = (uchar_t *)&(bsp->bs_filler[BPB_32_START_INDEX]);
289*fdc43e97SToomas Soome 
290*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[3] = *grabp++;
291*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[2] = *grabp++;
292*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[1] = *grabp++;
293*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.big_sectors_per_fat))[0] = *grabp++;
294*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.ext_flags))[1] = *grabp++;
295*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.ext_flags))[0] = *grabp++;
296*fdc43e97SToomas Soome 	wbpb->bpb32.fs_vers_lo = *grabp++;
297*fdc43e97SToomas Soome 	wbpb->bpb32.fs_vers_hi = *grabp++;
298*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.root_dir_clust))[3] = *grabp++;
299*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.root_dir_clust))[2] = *grabp++;
300*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.root_dir_clust))[1] = *grabp++;
301*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.root_dir_clust))[0] = *grabp++;
302*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.fsinfosec))[1] = *grabp++;
303*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.fsinfosec))[0] = *grabp++;
304*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.backupboot))[1] = *grabp++;
305*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.backupboot))[0] = *grabp++;
306*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[0]))[1] = *grabp++;
307*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[0]))[0] = *grabp++;
308*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[1]))[1] = *grabp++;
309*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[1]))[0] = *grabp++;
310*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[2]))[1] = *grabp++;
311*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[2]))[0] = *grabp++;
312*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[3]))[1] = *grabp++;
313*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[3]))[0] = *grabp++;
314*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[4]))[1] = *grabp++;
315*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[4]))[0] = *grabp++;
316*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[5]))[1] = *grabp++;
317*fdc43e97SToomas Soome 	((uchar_t *)&(wbpb->bpb32.reserved[5]))[0] = *grabp++;
318*fdc43e97SToomas Soome }
319*fdc43e97SToomas Soome #endif	/* _BIG_ENDIAN */
320*fdc43e97SToomas Soome 
321*fdc43e97SToomas Soome char *
stat_actual_disk(const char * diskname,struct stat * info,char ** suffix)322*fdc43e97SToomas Soome stat_actual_disk(const char *diskname, struct stat *info, char **suffix)
323*fdc43e97SToomas Soome {
324*fdc43e97SToomas Soome 	char *actualdisk;
325*fdc43e97SToomas Soome 
326*fdc43e97SToomas Soome 	if (stat(diskname, info) != 0) {
327*fdc43e97SToomas Soome 		/*
328*fdc43e97SToomas Soome 		 *  Device named on command line doesn't exist.  That
329*fdc43e97SToomas Soome 		 *  probably means there is a partition-specifying
330*fdc43e97SToomas Soome 		 *  suffix attached to the actual disk name.
331*fdc43e97SToomas Soome 		 */
332*fdc43e97SToomas Soome 		if ((actualdisk = strdup(diskname)) == NULL) {
333*fdc43e97SToomas Soome 			(void) fprintf(stderr,
334*fdc43e97SToomas Soome 			    gettext("Out of memory for disk name.\n"));
335*fdc43e97SToomas Soome 			exit(2);
336*fdc43e97SToomas Soome 		}
337*fdc43e97SToomas Soome 		if ((*suffix = strchr(actualdisk, ':')) != NULL) {
338*fdc43e97SToomas Soome 			**suffix = '\0';
339*fdc43e97SToomas Soome 			(*suffix)++;
340*fdc43e97SToomas Soome 		}
341*fdc43e97SToomas Soome 
342*fdc43e97SToomas Soome 		if (stat(actualdisk, info)) {
343*fdc43e97SToomas Soome 			err(2, "Failed to stat disk device %s",
344*fdc43e97SToomas Soome 			    actualdisk);
345*fdc43e97SToomas Soome 		}
346*fdc43e97SToomas Soome 	} else {
347*fdc43e97SToomas Soome 		if ((actualdisk = strdup(diskname)) == NULL) {
348*fdc43e97SToomas Soome 			(void) fprintf(stderr,
349*fdc43e97SToomas Soome 			    gettext("Out of memory for disk name.\n"));
350*fdc43e97SToomas Soome 			exit(2);
351*fdc43e97SToomas Soome 		}
352*fdc43e97SToomas Soome 	}
353*fdc43e97SToomas Soome 
354*fdc43e97SToomas Soome 	return (actualdisk);
355*fdc43e97SToomas Soome }
356*fdc43e97SToomas Soome 
357*fdc43e97SToomas Soome extern void usage(void);
358*fdc43e97SToomas Soome 
359*fdc43e97SToomas Soome void
bad_arg(char * option)360*fdc43e97SToomas Soome bad_arg(char *option)
361*fdc43e97SToomas Soome {
362*fdc43e97SToomas Soome 	(void) fprintf(stderr,
363*fdc43e97SToomas Soome 	    gettext("Unrecognized option -o %s.\n"), option);
364*fdc43e97SToomas Soome 	usage();
365*fdc43e97SToomas Soome 	exit(2);
366*fdc43e97SToomas Soome }
367*fdc43e97SToomas Soome 
368*fdc43e97SToomas Soome void
missing_arg(char * option)369*fdc43e97SToomas Soome missing_arg(char *option)
370*fdc43e97SToomas Soome {
371*fdc43e97SToomas Soome 	(void) fprintf(stderr,
372*fdc43e97SToomas Soome 	    gettext("Option %s requires a value.\n"), option);
373*fdc43e97SToomas Soome 	usage();
374*fdc43e97SToomas Soome 	exit(3);
375*fdc43e97SToomas Soome }
376*fdc43e97SToomas Soome 
377*fdc43e97SToomas Soome static int
parse_drvnum(char * pn)378*fdc43e97SToomas Soome parse_drvnum(char *pn)
379*fdc43e97SToomas Soome {
380*fdc43e97SToomas Soome 	int drvnum;
381*fdc43e97SToomas Soome 
382*fdc43e97SToomas Soome 	/*
383*fdc43e97SToomas Soome 	 * Determine logical drive to seek after.
384*fdc43e97SToomas Soome 	 */
385*fdc43e97SToomas Soome 	if ((strlen(pn) == 1) && ((*pn >= 'c') && (*pn <= 'z'))) {
386*fdc43e97SToomas Soome 		drvnum = *pn - 'c' + 1;
387*fdc43e97SToomas Soome 	} else if ((*pn >= '0') && (*pn <= '9')) {
388*fdc43e97SToomas Soome 		char *d;
389*fdc43e97SToomas Soome 		int v = 0;
390*fdc43e97SToomas Soome 
391*fdc43e97SToomas Soome 		d = pn;
392*fdc43e97SToomas Soome 		while ((*d != '\0') && (*d >= '0') && (*d <= '9')) {
393*fdc43e97SToomas Soome 			v *= 10;
394*fdc43e97SToomas Soome 			v += *d - '0';
395*fdc43e97SToomas Soome 			d++;
396*fdc43e97SToomas Soome 		}
397*fdc43e97SToomas Soome 		if ((*d != '\0') || (v > 24)) {
398*fdc43e97SToomas Soome 			(void) fprintf(stderr,
399*fdc43e97SToomas Soome 			    gettext("%s: bogus logical drive specification.\n"),
400*fdc43e97SToomas Soome 			    pn);
401*fdc43e97SToomas Soome 			return (-1);
402*fdc43e97SToomas Soome 		}
403*fdc43e97SToomas Soome 		drvnum = v;
404*fdc43e97SToomas Soome 	} else if (strcmp(pn, "boot") == 0) {
405*fdc43e97SToomas Soome 		drvnum = 99;
406*fdc43e97SToomas Soome 	} else {
407*fdc43e97SToomas Soome 		(void) fprintf(stderr,
408*fdc43e97SToomas Soome 		    gettext("%s: bogus logical drive specification.\n"), pn);
409*fdc43e97SToomas Soome 		return (-1);
410*fdc43e97SToomas Soome 	}
411*fdc43e97SToomas Soome 
412*fdc43e97SToomas Soome 	return (drvnum);
413*fdc43e97SToomas Soome }
414*fdc43e97SToomas Soome 
415*fdc43e97SToomas Soome /*
416*fdc43e97SToomas Soome  * isDosDrive()
417*fdc43e97SToomas Soome  *	Boolean function.  Give it the systid field for an fdisk partition
418*fdc43e97SToomas Soome  *	and it decides if that's a systid that describes a DOS drive.  We
419*fdc43e97SToomas Soome  *	use systid values defined in sys/dktp/fdisk.h.
420*fdc43e97SToomas Soome  */
421*fdc43e97SToomas Soome static int
isDosDrive(uchar_t checkMe)422*fdc43e97SToomas Soome isDosDrive(uchar_t checkMe)
423*fdc43e97SToomas Soome {
424*fdc43e97SToomas Soome 	return ((checkMe == DOSOS12) || (checkMe == DOSOS16) ||
425*fdc43e97SToomas Soome 	    (checkMe == DOSHUGE) || (checkMe == FDISK_WINDOWS) ||
426*fdc43e97SToomas Soome 	    (checkMe == FDISK_EXT_WIN) || (checkMe == FDISK_FAT95) ||
427*fdc43e97SToomas Soome 	    (checkMe == DIAGPART));
428*fdc43e97SToomas Soome }
429*fdc43e97SToomas Soome 
430*fdc43e97SToomas Soome /*
431*fdc43e97SToomas Soome  * isDosExtended()
432*fdc43e97SToomas Soome  *	Boolean function.  Give it the systid field for an fdisk partition
433*fdc43e97SToomas Soome  *	and it decides if that's a systid that describes an extended DOS
434*fdc43e97SToomas Soome  *	partition.
435*fdc43e97SToomas Soome  */
436*fdc43e97SToomas Soome static int
isDosExtended(uchar_t checkMe)437*fdc43e97SToomas Soome isDosExtended(uchar_t checkMe)
438*fdc43e97SToomas Soome {
439*fdc43e97SToomas Soome 	return ((checkMe == EXTDOS) || (checkMe == FDISK_EXTLBA));
440*fdc43e97SToomas Soome }
441*fdc43e97SToomas Soome 
442*fdc43e97SToomas Soome /*
443*fdc43e97SToomas Soome  * isBootPart()
444*fdc43e97SToomas Soome  *	Boolean function.  Give it the systid field for an fdisk partition
445*fdc43e97SToomas Soome  *	and it decides if that's a systid that describes a Solaris boot
446*fdc43e97SToomas Soome  *	partition.
447*fdc43e97SToomas Soome  */
448*fdc43e97SToomas Soome static int
isBootPart(uchar_t checkMe)449*fdc43e97SToomas Soome isBootPart(uchar_t checkMe)
450*fdc43e97SToomas Soome {
451*fdc43e97SToomas Soome 	return (checkMe == X86BOOT);
452*fdc43e97SToomas Soome }
453*fdc43e97SToomas Soome 
454*fdc43e97SToomas Soome off64_t
findPartitionOffset(int fd,size_t bpsec,char * ldrive)455*fdc43e97SToomas Soome findPartitionOffset(int fd, size_t bpsec, char *ldrive)
456*fdc43e97SToomas Soome {
457*fdc43e97SToomas Soome 	struct ipart part[FD_NUMPART];
458*fdc43e97SToomas Soome 	struct mboot extmboot;
459*fdc43e97SToomas Soome 	struct mboot mb;
460*fdc43e97SToomas Soome 	diskaddr_t xstartsect;
461*fdc43e97SToomas Soome 	off64_t nextseek = 0;
462*fdc43e97SToomas Soome 	off64_t lastseek = 0;
463*fdc43e97SToomas Soome 	off64_t found = 0;
464*fdc43e97SToomas Soome 	off64_t error = -1;
465*fdc43e97SToomas Soome 	int logicalDriveCount = 0;
466*fdc43e97SToomas Soome 	int extendedPart = -1;
467*fdc43e97SToomas Soome 	int primaryPart = -1;
468*fdc43e97SToomas Soome 	int bootPart = -1;
469*fdc43e97SToomas Soome 	uint32_t xnumsect = 0;
470*fdc43e97SToomas Soome 	int drvnum;
471*fdc43e97SToomas Soome 	int driveIndex;
472*fdc43e97SToomas Soome 	int i;
473*fdc43e97SToomas Soome 	/*
474*fdc43e97SToomas Soome 	 * Count of drives in the current extended partition's
475*fdc43e97SToomas Soome 	 * FDISK table, and indexes of the drives themselves.
476*fdc43e97SToomas Soome 	 */
477*fdc43e97SToomas Soome 	int extndDrives[FD_NUMPART];
478*fdc43e97SToomas Soome 	int numDrives = 0;
479*fdc43e97SToomas Soome 	/*
480*fdc43e97SToomas Soome 	 * Count of drives (beyond primary) in master boot record's
481*fdc43e97SToomas Soome 	 * FDISK table, and indexes of the drives themselves.
482*fdc43e97SToomas Soome 	 */
483*fdc43e97SToomas Soome 	int extraDrives[FD_NUMPART];
484*fdc43e97SToomas Soome 	int numExtraDrives = 0;
485*fdc43e97SToomas Soome 
486*fdc43e97SToomas Soome 	if ((drvnum = parse_drvnum(ldrive)) < 0)
487*fdc43e97SToomas Soome 		return (error);
488*fdc43e97SToomas Soome 
489*fdc43e97SToomas Soome 	if (read(fd, &mb, bpsec) != (ssize_t)bpsec) {
490*fdc43e97SToomas Soome 		(void) fprintf(stderr,
491*fdc43e97SToomas Soome 		    gettext("Couldn't read a Master Boot Record\n"));
492*fdc43e97SToomas Soome 		return (error);
493*fdc43e97SToomas Soome 	}
494*fdc43e97SToomas Soome 
495*fdc43e97SToomas Soome 	if (ltohs(mb.signature) != BOOTSECSIG) {
496*fdc43e97SToomas Soome 		(void) fprintf(stderr,
497*fdc43e97SToomas Soome 		    gettext("Bad signature on master boot record (%x)\n"),
498*fdc43e97SToomas Soome 		    ltohs(mb.signature));
499*fdc43e97SToomas Soome 		return (error);
500*fdc43e97SToomas Soome 	}
501*fdc43e97SToomas Soome 
502*fdc43e97SToomas Soome 	/*
503*fdc43e97SToomas Soome 	 * Copy partition table into memory
504*fdc43e97SToomas Soome 	 */
505*fdc43e97SToomas Soome 	(void) memcpy(part, mb.parts, sizeof (part));
506*fdc43e97SToomas Soome 
507*fdc43e97SToomas Soome 	/*
508*fdc43e97SToomas Soome 	 * Get a summary of what is in the Master FDISK table.
509*fdc43e97SToomas Soome 	 * Normally we expect to find one partition marked as a DOS drive.
510*fdc43e97SToomas Soome 	 * This partition is the one Windows calls the primary dos partition.
511*fdc43e97SToomas Soome 	 * If the machine has any logical drives then we also expect
512*fdc43e97SToomas Soome 	 * to find a partition marked as an extended DOS partition.
513*fdc43e97SToomas Soome 	 *
514*fdc43e97SToomas Soome 	 * Sometimes we'll find multiple partitions marked as DOS drives.
515*fdc43e97SToomas Soome 	 * The Solaris fdisk program allows these partitions
516*fdc43e97SToomas Soome 	 * to be created, but Windows fdisk no longer does.  We still need
517*fdc43e97SToomas Soome 	 * to support these, though, since Windows does.  We also need to fix
518*fdc43e97SToomas Soome 	 * our fdisk to behave like the Windows version.
519*fdc43e97SToomas Soome 	 *
520*fdc43e97SToomas Soome 	 * It turns out that some off-the-shelf media have *only* an
521*fdc43e97SToomas Soome 	 * Extended partition, so we need to deal with that case as
522*fdc43e97SToomas Soome 	 * well.
523*fdc43e97SToomas Soome 	 *
524*fdc43e97SToomas Soome 	 * Only a single (the first) Extended or Boot Partition will
525*fdc43e97SToomas Soome 	 * be recognized.  Any others will be ignored.
526*fdc43e97SToomas Soome 	 */
527*fdc43e97SToomas Soome 	for (i = 0; i < FD_NUMPART; i++) {
528*fdc43e97SToomas Soome 		if (isDosDrive(part[i].systid)) {
529*fdc43e97SToomas Soome 			if (primaryPart < 0) {
530*fdc43e97SToomas Soome 				logicalDriveCount++;
531*fdc43e97SToomas Soome 				primaryPart = i;
532*fdc43e97SToomas Soome 			} else {
533*fdc43e97SToomas Soome 				extraDrives[numExtraDrives++] = i;
534*fdc43e97SToomas Soome 			}
535*fdc43e97SToomas Soome 			continue;
536*fdc43e97SToomas Soome 		}
537*fdc43e97SToomas Soome 		if ((extendedPart < 0) && isDosExtended(part[i].systid)) {
538*fdc43e97SToomas Soome 			extendedPart = i;
539*fdc43e97SToomas Soome 			continue;
540*fdc43e97SToomas Soome 		}
541*fdc43e97SToomas Soome 		if ((bootPart < 0) && isBootPart(part[i].systid)) {
542*fdc43e97SToomas Soome 			bootPart = i;
543*fdc43e97SToomas Soome 			continue;
544*fdc43e97SToomas Soome 		}
545*fdc43e97SToomas Soome 	}
546*fdc43e97SToomas Soome 
547*fdc43e97SToomas Soome 	if (drvnum == BOOT_PARTITION_DRIVE) {
548*fdc43e97SToomas Soome 		if (bootPart < 0) {
549*fdc43e97SToomas Soome 			(void) fprintf(stderr,
550*fdc43e97SToomas Soome 			    gettext("No boot partition found on drive\n"));
551*fdc43e97SToomas Soome 			return (error);
552*fdc43e97SToomas Soome 		}
553*fdc43e97SToomas Soome 		found = ltohi(part[bootPart].relsect) * bpsec;
554*fdc43e97SToomas Soome 		return (found);
555*fdc43e97SToomas Soome 	}
556*fdc43e97SToomas Soome 
557*fdc43e97SToomas Soome 	if (drvnum == PRIMARY_DOS_DRIVE && primaryPart >= 0) {
558*fdc43e97SToomas Soome 		found = ltohi(part[primaryPart].relsect) * bpsec;
559*fdc43e97SToomas Soome 		return (found);
560*fdc43e97SToomas Soome 	}
561*fdc43e97SToomas Soome 
562*fdc43e97SToomas Soome 	/*
563*fdc43e97SToomas Soome 	 * We are not looking for the C: drive (or there was no primary
564*fdc43e97SToomas Soome 	 * drive found), so we had better have an extended partition or
565*fdc43e97SToomas Soome 	 * extra drives in the Master FDISK table.
566*fdc43e97SToomas Soome 	 */
567*fdc43e97SToomas Soome 	if ((extendedPart < 0) && (numExtraDrives == 0)) {
568*fdc43e97SToomas Soome 		(void) fprintf(stderr,
569*fdc43e97SToomas Soome 		    gettext("No such logical drive "
570*fdc43e97SToomas Soome 		    "(missing extended partition entry)\n"));
571*fdc43e97SToomas Soome 		return (error);
572*fdc43e97SToomas Soome 	}
573*fdc43e97SToomas Soome 
574*fdc43e97SToomas Soome 	if (extendedPart >= 0) {
575*fdc43e97SToomas Soome 		nextseek = xstartsect = ltohi(part[extendedPart].relsect);
576*fdc43e97SToomas Soome 		xnumsect = ltohi(part[extendedPart].numsect);
577*fdc43e97SToomas Soome 		do {
578*fdc43e97SToomas Soome 			/*
579*fdc43e97SToomas Soome 			 *  If the seek would not cause us to change
580*fdc43e97SToomas Soome 			 *  position on the drive, then we're out of
581*fdc43e97SToomas Soome 			 *  extended partitions to examine.
582*fdc43e97SToomas Soome 			 */
583*fdc43e97SToomas Soome 			if (nextseek == lastseek)
584*fdc43e97SToomas Soome 				break;
585*fdc43e97SToomas Soome 			logicalDriveCount += numDrives;
586*fdc43e97SToomas Soome 			/*
587*fdc43e97SToomas Soome 			 *  Seek the next extended partition, and find
588*fdc43e97SToomas Soome 			 *  logical drives within it.
589*fdc43e97SToomas Soome 			 */
590*fdc43e97SToomas Soome 			if (lseek64(fd, nextseek * bpsec, SEEK_SET) < 0 ||
591*fdc43e97SToomas Soome 			    read(fd, &extmboot, sizeof (extmboot)) !=
592*fdc43e97SToomas Soome 			    sizeof (extmboot)) {
593*fdc43e97SToomas Soome 				perror(gettext("Unable to read extended "
594*fdc43e97SToomas Soome 				    "partition record"));
595*fdc43e97SToomas Soome 				return (error);
596*fdc43e97SToomas Soome 			}
597*fdc43e97SToomas Soome 			(void) memcpy(part, extmboot.parts, sizeof (part));
598*fdc43e97SToomas Soome 			lastseek = nextseek;
599*fdc43e97SToomas Soome 			if (ltohs(extmboot.signature) != MBB_MAGIC) {
600*fdc43e97SToomas Soome 				(void) fprintf(stderr,
601*fdc43e97SToomas Soome 				    gettext("Bad signature on "
602*fdc43e97SToomas Soome 				    "extended partition\n"));
603*fdc43e97SToomas Soome 				return (error);
604*fdc43e97SToomas Soome 			}
605*fdc43e97SToomas Soome 			/*
606*fdc43e97SToomas Soome 			 *  Count up drives, and track where the next
607*fdc43e97SToomas Soome 			 *  extended partition is in case we need it.  We
608*fdc43e97SToomas Soome 			 *  are expecting only one extended partition.  If
609*fdc43e97SToomas Soome 			 *  there is more than one we'll only go to the
610*fdc43e97SToomas Soome 			 *  first one we see, but warn about ignoring.
611*fdc43e97SToomas Soome 			 */
612*fdc43e97SToomas Soome 			numDrives = 0;
613*fdc43e97SToomas Soome 			for (i = 0; i < FD_NUMPART; i++) {
614*fdc43e97SToomas Soome 				if (isDosDrive(part[i].systid)) {
615*fdc43e97SToomas Soome 					extndDrives[numDrives++] = i;
616*fdc43e97SToomas Soome 					continue;
617*fdc43e97SToomas Soome 				} else if (isDosExtended(part[i].systid)) {
618*fdc43e97SToomas Soome 					if (nextseek != lastseek) {
619*fdc43e97SToomas Soome 						/*
620*fdc43e97SToomas Soome 						 * Already found an extended
621*fdc43e97SToomas Soome 						 * partition in this table.
622*fdc43e97SToomas Soome 						 */
623*fdc43e97SToomas Soome 						(void) fprintf(stderr,
624*fdc43e97SToomas Soome 						    gettext("WARNING: "
625*fdc43e97SToomas Soome 						    "Ignoring unexpected "
626*fdc43e97SToomas Soome 						    "additional extended "
627*fdc43e97SToomas Soome 						    "partition"));
628*fdc43e97SToomas Soome 						continue;
629*fdc43e97SToomas Soome 					}
630*fdc43e97SToomas Soome 					nextseek = xstartsect +
631*fdc43e97SToomas Soome 					    ltohi(part[i].relsect);
632*fdc43e97SToomas Soome 					continue;
633*fdc43e97SToomas Soome 				}
634*fdc43e97SToomas Soome 			}
635*fdc43e97SToomas Soome 		} while (drvnum > logicalDriveCount + numDrives);
636*fdc43e97SToomas Soome 
637*fdc43e97SToomas Soome 		if (drvnum <= logicalDriveCount + numDrives) {
638*fdc43e97SToomas Soome 			/*
639*fdc43e97SToomas Soome 			 * The number of logical drives we've found thus
640*fdc43e97SToomas Soome 			 * far is enough to get us to the one we were
641*fdc43e97SToomas Soome 			 * searching for.
642*fdc43e97SToomas Soome 			 */
643*fdc43e97SToomas Soome 			driveIndex = logicalDriveCount + numDrives - drvnum;
644*fdc43e97SToomas Soome 			found =
645*fdc43e97SToomas Soome 			    ltohi(part[extndDrives[driveIndex]].relsect) +
646*fdc43e97SToomas Soome 			    lastseek;
647*fdc43e97SToomas Soome 			if (found > (xstartsect + xnumsect)) {
648*fdc43e97SToomas Soome 				(void) fprintf(stderr,
649*fdc43e97SToomas Soome 				    gettext("Logical drive start sector (%d) "
650*fdc43e97SToomas Soome 				    "is not within the partition!\n"), found);
651*fdc43e97SToomas Soome 				return (error);
652*fdc43e97SToomas Soome 			} else {
653*fdc43e97SToomas Soome 				found *= bpsec;
654*fdc43e97SToomas Soome 			}
655*fdc43e97SToomas Soome 			return (found);
656*fdc43e97SToomas Soome 		} else {
657*fdc43e97SToomas Soome 			/*
658*fdc43e97SToomas Soome 			 * We ran out of extended dos partition
659*fdc43e97SToomas Soome 			 * drives.  The only hope now is to go
660*fdc43e97SToomas Soome 			 * back to extra drives defined in the master
661*fdc43e97SToomas Soome 			 * fdisk table.  But we overwrote that table
662*fdc43e97SToomas Soome 			 * already, so we must load it in again.
663*fdc43e97SToomas Soome 			 */
664*fdc43e97SToomas Soome 			logicalDriveCount += numDrives;
665*fdc43e97SToomas Soome 			(void) memcpy(part, mb.parts, sizeof (part));
666*fdc43e97SToomas Soome 		}
667*fdc43e97SToomas Soome 	}
668*fdc43e97SToomas Soome 	/*
669*fdc43e97SToomas Soome 	 *  Still haven't found the drive, is it an extra
670*fdc43e97SToomas Soome 	 *  drive defined in the main FDISK table?
671*fdc43e97SToomas Soome 	 */
672*fdc43e97SToomas Soome 	if (drvnum <= logicalDriveCount + numExtraDrives) {
673*fdc43e97SToomas Soome 		driveIndex = logicalDriveCount + numExtraDrives - drvnum;
674*fdc43e97SToomas Soome 		found = ltohi(part[extraDrives[driveIndex]].relsect) * bpsec;
675*fdc43e97SToomas Soome 		return (found);
676*fdc43e97SToomas Soome 	}
677*fdc43e97SToomas Soome 	return (error);
678*fdc43e97SToomas Soome }
679