fdisk.c revision 1.29 1 1.29 ws /* $NetBSD: fdisk.c,v 1.29 1998/10/02 17:23:22 ws Exp $ */
2 1.10 cgd
3 1.4 mycroft /*
4 1.1 cgd * Mach Operating System
5 1.1 cgd * Copyright (c) 1992 Carnegie Mellon University
6 1.1 cgd * All Rights Reserved.
7 1.4 mycroft *
8 1.1 cgd * Permission to use, copy, modify and distribute this software and its
9 1.1 cgd * documentation is hereby granted, provided that both the copyright
10 1.1 cgd * notice and this permission notice appear in all copies of the
11 1.1 cgd * software, derivative works or modified versions, and any portions
12 1.1 cgd * thereof, and that both notices appear in supporting documentation.
13 1.4 mycroft *
14 1.1 cgd * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 1.1 cgd * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 1.1 cgd * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 1.4 mycroft *
18 1.1 cgd * Carnegie Mellon requests users of this software to return to
19 1.4 mycroft *
20 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
21 1.1 cgd * School of Computer Science
22 1.1 cgd * Carnegie Mellon University
23 1.1 cgd * Pittsburgh PA 15213-3890
24 1.4 mycroft *
25 1.1 cgd * any improvements or extensions that they make and grant Carnegie Mellon
26 1.1 cgd * the rights to redistribute these changes.
27 1.1 cgd */
28 1.1 cgd
29 1.16 phil #include <sys/cdefs.h>
30 1.16 phil
31 1.2 mycroft #ifndef lint
32 1.29 ws __RCSID("$NetBSD: fdisk.c,v 1.29 1998/10/02 17:23:22 ws Exp $");
33 1.2 mycroft #endif /* not lint */
34 1.2 mycroft
35 1.1 cgd #include <sys/types.h>
36 1.1 cgd #include <sys/disklabel.h>
37 1.4 mycroft #include <sys/ioctl.h>
38 1.18 lukem #include <sys/param.h>
39 1.1 cgd #include <sys/stat.h>
40 1.4 mycroft
41 1.8 cgd #include <ctype.h>
42 1.4 mycroft #include <err.h>
43 1.18 lukem #include <errno.h>
44 1.1 cgd #include <fcntl.h>
45 1.18 lukem #include <paths.h>
46 1.4 mycroft #include <stdio.h>
47 1.4 mycroft #include <stdlib.h>
48 1.8 cgd #include <string.h>
49 1.8 cgd #include <unistd.h>
50 1.19 lukem #include <util.h>
51 1.1 cgd
52 1.1 cgd #define LBUF 100
53 1.1 cgd static char lbuf[LBUF];
54 1.1 cgd
55 1.1 cgd /*
56 1.1 cgd * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
57 1.1 cgd * Copyright (c) 1989 Robert. V. Baron
58 1.1 cgd * Created.
59 1.1 cgd */
60 1.1 cgd
61 1.1 cgd char *disk = "/dev/rwd0d";
62 1.1 cgd
63 1.1 cgd struct disklabel disklabel; /* disk parameters */
64 1.1 cgd
65 1.5 mycroft int cylinders, sectors, heads, cylindersectors, disksectors;
66 1.1 cgd
67 1.4 mycroft struct mboot {
68 1.1 cgd unsigned char padding[2]; /* force the longs to be long alligned */
69 1.1 cgd unsigned char bootinst[DOSPARTOFF];
70 1.1 cgd struct dos_partition parts[4];
71 1.1 cgd unsigned short int signature;
72 1.1 cgd };
73 1.1 cgd struct mboot mboot;
74 1.1 cgd
75 1.1 cgd #define ACTIVE 0x80
76 1.1 cgd #define BOOT_MAGIC 0xAA55
77 1.1 cgd
78 1.5 mycroft int dos_cylinders;
79 1.1 cgd int dos_heads;
80 1.1 cgd int dos_sectors;
81 1.5 mycroft int dos_cylindersectors;
82 1.1 cgd
83 1.4 mycroft #define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
84 1.4 mycroft #define DOSCYL(c) ((c) & 0xff)
85 1.28 ws
86 1.28 ws #define MAXCYL 1024
87 1.4 mycroft int partition = -1;
88 1.4 mycroft
89 1.4 mycroft int a_flag; /* set active partition */
90 1.28 ws int i_flag; /* init bootcode */
91 1.4 mycroft int u_flag; /* update partition data */
92 1.15 phil int sh_flag; /* Output data as shell defines */
93 1.15 phil int f_flag; /* force --not interactive */
94 1.15 phil int s_flag; /* set id,offset,size */
95 1.16 phil int b_flag; /* Set cyl, heads, secs (as c/h/s) */
96 1.16 phil int b_cyl, b_head, b_sec; /* b_flag values. */
97 1.4 mycroft
98 1.4 mycroft unsigned char bootcode[] = {
99 1.4 mycroft 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
100 1.4 mycroft 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
101 1.4 mycroft 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
102 1.4 mycroft 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
103 1.4 mycroft 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
104 1.4 mycroft 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
105 1.4 mycroft 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
106 1.4 mycroft 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
107 1.1 cgd 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
108 1.1 cgd 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
109 1.1 cgd 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
110 1.4 mycroft 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
111 1.1 cgd 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
112 1.1 cgd 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
113 1.1 cgd 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
114 1.1 cgd 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
115 1.4 mycroft 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
116 1.1 cgd
117 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
120 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
123 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
125 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
126 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
127 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
128 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
129 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
130 1.1 cgd };
131 1.1 cgd
132 1.25 drochner static char reserved[] = "reserved";
134 1.4 mycroft
135 1.4 mycroft struct part_type {
136 1.4 mycroft int type;
137 1.4 mycroft char *name;
138 1.4 mycroft } part_types[] = {
139 1.4 mycroft {0x00, "unused"},
140 1.4 mycroft {0x01, "Primary DOS with 12 bit FAT"},
141 1.4 mycroft {0x02, "XENIX / filesystem"},
142 1.13 perry {0x03, "XENIX /usr filesystem"},
143 1.25 drochner {0x04, "Primary DOS with 16 bit FAT <32M"},
144 1.13 perry {0x05, "Extended partition"},
145 1.13 perry {0x06, "Primary 'big' DOS, 16-bit FAT (> 32MB)"},
146 1.25 drochner {0x07, "OS/2 HPFS or NTFS or QNX2 or Advanced UNIX"},
147 1.25 drochner {0x08, "AIX filesystem or OS/2 (thru v1.3) or DELL multiple drives"
148 1.4 mycroft "or Commodore DOS or SplitDrive"},
149 1.13 perry {0x09, "AIX boot partition or Coherent"},
150 1.25 drochner {0x0A, "OS/2 Boot Manager or Coherent swap or OPUS"},
151 1.25 drochner {0x0b, "Primary DOS with 32 bit FAT"},
152 1.25 drochner {0x0c, "Primary DOS with 32 bit FAT - LBA"},
153 1.25 drochner {0x0d, "Type 7??? - LBA"},
154 1.25 drochner {0x0E, "DOS (16-bit FAT) - LBA"},
155 1.4 mycroft {0x0F, "Ext. partition - LBA"},
156 1.13 perry {0x10, "OPUS"},
157 1.13 perry {0x11, "OS/2 BM: hidden DOS 12-bit FAT"},
158 1.25 drochner {0x12, "Compaq diagnostics"},
159 1.13 perry {0x14, "OS/2 BM: hidden DOS 16-bit FAT <32M or Novell DOS 7.0 bug"},
160 1.13 perry {0x16, "OS/2 BM: hidden DOS 16-bit FAT >=32M"},
161 1.13 perry {0x17, "OS/2 BM: hidden IFS"},
162 1.25 drochner {0x18, "AST Windows swapfile"},
163 1.25 drochner {0x19, "Willowtech Photon coS"},
164 1.25 drochner {0x1e, "hidden FAT95"},
165 1.25 drochner {0x20, "Willowsoft OFS1"},
166 1.25 drochner {0x21, reserved},
167 1.13 perry {0x23, reserved},
168 1.25 drochner {0x24, "NEC DOS"},
169 1.25 drochner {0x26, reserved},
170 1.25 drochner {0x31, reserved},
171 1.25 drochner {0x33, reserved},
172 1.25 drochner {0x34, reserved},
173 1.25 drochner {0x36, reserved},
174 1.13 perry {0x38, "Theos"},
175 1.25 drochner {0x3C, "PartitionMagic recovery"},
176 1.25 drochner {0x40, "VENIX 286 or LynxOS"},
177 1.13 perry {0x41, "Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot"},
178 1.13 perry {0x42, "SFS or Linux swap (sharing disk with DRDOS)"},
179 1.13 perry {0x43, "Linux native (sharing disk with DRDOS)"},
180 1.13 perry {0x50, "DM (disk manager)"},
181 1.4 mycroft {0x51, "DM6 Aux1 (or Novell)"},
182 1.13 perry {0x52, "CP/M or Microport SysV/AT"},
183 1.25 drochner {0x53, "DM6 Aux3"},
184 1.13 perry {0x54, "DM6 DDO"},
185 1.13 perry {0x55, "EZ-Drive (disk manager)"},
186 1.13 perry {0x56, "Golden Bow (disk manager)"},
187 1.13 perry {0x5C, "Priam Edisk (disk manager)"},
188 1.25 drochner {0x61, "SpeedStor"},
189 1.25 drochner {0x63, "GNU HURD or Mach or Sys V/386 (such as ISC UNIX) or MtXinu"},
190 1.4 mycroft {0x64, "Novell Netware 2.xx or Speedstore"},
191 1.25 drochner {0x65, "Novell Netware 3.xx"},
192 1.25 drochner {0x66, "Novell 386 Netware"},
193 1.25 drochner {0x67, "Novell"},
194 1.25 drochner {0x68, "Novell"},
195 1.13 perry {0x69, "Novell"},
196 1.25 drochner {0x70, "DiskSecure Multi-Boot"},
197 1.25 drochner {0x71, reserved},
198 1.25 drochner {0x73, reserved},
199 1.13 perry {0x74, reserved},
200 1.25 drochner {0x75, "PC/IX"},
201 1.13 perry {0x76, reserved},
202 1.13 perry {0x77, "QNX4.x"},
203 1.13 perry {0x78, "QNX4.x 2nd part"},
204 1.13 perry {0x79, "QNX4.x 3rd part"},
205 1.13 perry {0x80, "MINIX until 1.4a"},
206 1.25 drochner {0x81, "MINIX since 1.4b, early Linux, Mitac dmgr"},
207 1.13 perry {0x82, "Linux swap or Prime or Solaris"},
208 1.13 perry {0x83, "Linux native"},
209 1.13 perry {0x84, "OS/2 hidden C: drive"},
210 1.25 drochner {0x85, "Linux extended"},
211 1.25 drochner {0x86, "NT FAT volume set"},
212 1.4 mycroft {0x87, "NTFS volume set or HPFS mirrored"},
213 1.4 mycroft {0x93, "Amoeba filesystem"},
214 1.25 drochner {0x94, "Amoeba bad block table"},
215 1.25 drochner {0x99, "Mylex EISA SCSI"},
216 1.13 perry {0x9f, "BSDI?"},
217 1.25 drochner {0xA0, "IBM Thinkpad hibernation"},
218 1.25 drochner {0xa1, reserved},
219 1.25 drochner {0xa3, reserved},
220 1.25 drochner {0xa4, reserved},
221 1.13 perry {0xA5, "FreeBSD or 386BSD or old NetBSD"},
222 1.13 perry {0xA6, "OpenBSD"},
223 1.25 drochner {0xA7, "NeXTSTEP 486"},
224 1.25 drochner {0xa9, "NetBSD"},
225 1.25 drochner {0xb1, reserved},
226 1.25 drochner {0xb3, reserved},
227 1.25 drochner {0xb4, reserved},
228 1.4 mycroft {0xb6, reserved},
229 1.4 mycroft {0xB7, "BSDI BSD/386 filesystem"},
230 1.25 drochner {0xB8, "BSDI BSD/386 swap"},
231 1.13 perry {0xc0, "CTOS"},
232 1.13 perry {0xC1, "DRDOS/sec (FAT-12)"},
233 1.13 perry {0xC4, "DRDOS/sec (FAT-16, < 32M)"},
234 1.25 drochner {0xC6, "DRDOS/sec (FAT-16, >= 32M)"},
235 1.25 drochner {0xC7, "Syrinx (Cyrnix?) or HPFS disabled"},
236 1.13 perry {0xd8, "CP/M 86"},
237 1.13 perry {0xDB, "CP/M or Concurrent CP/M or Concurrent DOS or CTOS"},
238 1.25 drochner {0xE1, "DOS access or SpeedStor 12-bit FAT extended partition"},
239 1.13 perry {0xE3, "DOS R/O or SpeedStor or Storage Dimensions"},
240 1.25 drochner {0xE4, "SpeedStor 16-bit FAT extended partition < 1024 cyl."},
241 1.25 drochner {0xe5, reserved},
242 1.25 drochner {0xe6, reserved},
243 1.4 mycroft {0xF1, "SpeedStor or Storage Dimensions"},
244 1.25 drochner {0xF2, "DOS 3.3+ Secondary"},
245 1.25 drochner {0xf3, reserved},
246 1.25 drochner {0xF4, "SpeedStor large partition or Storage Dimensions"},
247 1.25 drochner {0xf6, reserved},
248 1.13 perry {0xFE, "SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML"},
249 1.1 cgd {0xFF, "Xenix Bad Block Table"},
250 1.1 cgd };
251 1.4 mycroft
252 1.4 mycroft void usage __P((void));
253 1.4 mycroft void print_s0 __P((int));
254 1.28 ws void print_part __P((int));
255 1.11 ghudson void init_sector0 __P((int, int));
256 1.11 ghudson void intuit_translated_geometry __P((void));
257 1.11 ghudson int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t,
258 1.11 ghudson quad_t));
259 1.15 phil int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t));
260 1.4 mycroft void change_part __P((int, int, int, int));
261 1.4 mycroft void print_params __P((void));
262 1.4 mycroft void change_active __P((int));
263 1.4 mycroft void get_params_to_use __P((void));
264 1.4 mycroft void dos __P((int, unsigned char *, unsigned char *, unsigned char *));
265 1.4 mycroft int open_disk __P((int));
266 1.4 mycroft int read_disk __P((int, void *));
267 1.4 mycroft int write_disk __P((int, void *));
268 1.4 mycroft int get_params __P((void));
269 1.4 mycroft int read_s0 __P((void));
270 1.4 mycroft int write_s0 __P((void));
271 1.5 mycroft int yesno __P((char *));
272 1.4 mycroft void decimal __P((char *, int *));
273 1.4 mycroft int type_match __P((const void *, const void *));
274 1.16 phil char *get_type __P((int));
275 1.16 phil int get_mapping __P((int, int *, int *, int *, long *));
276 1.16 phil
277 1.16 phil static inline unsigned short getshort __P((void *));
278 1.16 phil static inline void putshort __P((void *p, unsigned short));
279 1.16 phil static inline unsigned long getlong __P((void *));
280 1.16 phil static inline void putlong __P((void *, unsigned long));
281 1.16 phil
282 1.16 phil
283 1.1 cgd int main __P((int, char **));
284 1.4 mycroft
285 1.1 cgd int
286 1.4 mycroft main(argc, argv)
287 1.4 mycroft int argc;
288 1.1 cgd char *argv[];
289 1.4 mycroft {
290 1.4 mycroft int ch;
291 1.1 cgd int part;
292 1.15 phil
293 1.15 phil int csysid, cstart, csize; /* For the b_flag. */
294 1.16 phil
295 1.15 phil a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
296 1.16 phil csysid = cstart = csize = 0;
297 1.4 mycroft while ((ch = getopt(argc, argv, "0123Safius:b:")) != -1)
298 1.4 mycroft switch (ch) {
299 1.4 mycroft case '0':
300 1.4 mycroft partition = 0;
301 1.4 mycroft break;
302 1.4 mycroft case '1':
303 1.4 mycroft partition = 1;
304 1.4 mycroft break;
305 1.4 mycroft case '2':
306 1.4 mycroft partition = 2;
307 1.4 mycroft break;
308 1.4 mycroft case '3':
309 1.4 mycroft partition = 3;
310 1.15 phil break;
311 1.15 phil case 'S':
312 1.15 phil sh_flag = 1;
313 1.4 mycroft break;
314 1.4 mycroft case 'a':
315 1.4 mycroft a_flag = 1;
316 1.15 phil break;
317 1.15 phil case 'f':
318 1.15 phil f_flag = 1;
319 1.4 mycroft break;
320 1.4 mycroft case 'i':
321 1.15 phil i_flag = 1;
322 1.4 mycroft break;
323 1.4 mycroft case 'u':
324 1.1 cgd u_flag = 1;
325 1.14 phil break;
326 1.14 phil case 's':
327 1.16 phil s_flag = 1;
328 1.16 phil if (sscanf (optarg, "%d/%d/%d",
329 1.16 phil &csysid, &cstart, &csize) != 3) {
330 1.16 phil (void)fprintf (stderr, "%s: Bad argument "
331 1.16 phil "to the -s flag.\n",
332 1.16 phil argv[0]);
333 1.16 phil exit (1);
334 1.16 phil }
335 1.16 phil break;
336 1.16 phil case 'b':
337 1.16 phil b_flag = 1;
338 1.16 phil if (sscanf (optarg, "%d/%d/%d",
339 1.16 phil &b_cyl, &b_head, &b_sec) != 3) {
340 1.16 phil (void)fprintf (stderr, "%s: Bad argument "
341 1.16 phil "to the -b flag.\n",
342 1.16 phil argv[0]);
343 1.16 phil exit (1);
344 1.28 ws }
345 1.28 ws if (b_cyl > MAXCYL)
346 1.14 phil b_cyl = MAXCYL;
347 1.4 mycroft break;
348 1.4 mycroft default:
349 1.1 cgd usage();
350 1.4 mycroft }
351 1.4 mycroft argc -= optind;
352 1.1 cgd argv += optind;
353 1.15 phil
354 1.15 phil if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
355 1.15 phil usage();
356 1.15 phil
357 1.15 phil if (partition == -1 && s_flag) {
358 1.15 phil (void) fprintf (stderr,
359 1.14 phil "-s flag requires a partition selected.\n");
360 1.15 phil usage();
361 1.15 phil }
362 1.1 cgd
363 1.1 cgd if (argc > 0)
364 1.4 mycroft disk = argv[0];
365 1.4 mycroft
366 1.1 cgd if (open_disk(a_flag || i_flag || u_flag) < 0)
367 1.1 cgd exit(1);
368 1.11 ghudson
369 1.28 ws if (read_s0())
370 1.11 ghudson init_sector0(sectors > 63 ? 63 : sectors, 1);
371 1.11 ghudson
372 1.11 ghudson intuit_translated_geometry();
373 1.17 phil
374 1.14 phil if (!sh_flag && !f_flag)
375 1.15 phil printf("******* Working on device %s *******\n", disk);
376 1.15 phil
377 1.16 phil
378 1.1 cgd if ((i_flag || u_flag) && (!f_flag || b_flag))
379 1.1 cgd get_params_to_use();
380 1.15 phil
381 1.28 ws if (i_flag)
382 1.15 phil init_sector0(dos_sectors > 63 ? 63 : dos_sectors, 0);
383 1.17 phil
384 1.14 phil if (!sh_flag && !f_flag)
385 1.14 phil printf("Warning: BIOS sector numbering starts with sector 1\n");
386 1.15 phil
387 1.15 phil /* Do the update stuff! */
388 1.15 phil if (u_flag) {
389 1.15 phil if (!f_flag)
390 1.15 phil printf("Information from DOS bootblock is:\n");
391 1.15 phil if (partition == -1)
392 1.15 phil for (part = 0; part < NDOSPART; part++)
393 1.15 phil change_part(part,-1, -1, -1);
394 1.15 phil else
395 1.4 mycroft change_part(partition, csysid, cstart, csize);
396 1.15 phil } else
397 1.15 phil if (!i_flag)
398 1.1 cgd print_s0(partition);
399 1.15 phil
400 1.1 cgd if (a_flag)
401 1.1 cgd change_active(partition);
402 1.15 phil
403 1.15 phil if (u_flag || a_flag || i_flag) {
404 1.15 phil if (!f_flag) {
405 1.15 phil printf("\nWe haven't changed the partition table "
406 1.15 phil "yet. This is your last chance.\n");
407 1.15 phil print_s0(-1);
408 1.15 phil if (yesno("Should we write new partition table?"))
409 1.15 phil write_s0();
410 1.1 cgd } else
411 1.1 cgd write_s0();
412 1.1 cgd }
413 1.1 cgd
414 1.4 mycroft exit(0);
415 1.1 cgd }
416 1.4 mycroft
417 1.4 mycroft void
418 1.4 mycroft usage()
419 1.15 phil {
420 1.16 phil (void)fprintf(stderr, "usage: fdisk [-aiufS] [-0|-1|-2|-3] "
421 1.4 mycroft "[device]\n");
422 1.1 cgd exit(1);
423 1.1 cgd }
424 1.4 mycroft
425 1.1 cgd void
426 1.4 mycroft print_s0(which)
427 1.1 cgd int which;
428 1.4 mycroft {
429 1.1 cgd int part;
430 1.1 cgd
431 1.15 phil print_params();
432 1.15 phil if (!sh_flag)
433 1.4 mycroft printf("Information from DOS bootblock is:\n");
434 1.15 phil if (which == -1) {
435 1.15 phil for (part = 0; part < NDOSPART; part++) {
436 1.15 phil if (!sh_flag)
437 1.15 phil printf("%d: ", part);
438 1.15 phil print_part(part);
439 1.4 mycroft }
440 1.1 cgd } else
441 1.1 cgd print_part(which);
442 1.1 cgd }
443 1.1 cgd
444 1.1 cgd static struct dos_partition mtpart = { 0 };
445 1.12 thorpej
446 1.12 thorpej static inline unsigned short
447 1.12 thorpej getshort(p)
448 1.12 thorpej void *p;
449 1.12 thorpej {
450 1.12 thorpej unsigned char *cp = p;
451 1.12 thorpej
452 1.12 thorpej return cp[0] | (cp[1] << 8);
453 1.12 thorpej }
454 1.12 thorpej
455 1.12 thorpej static inline void
456 1.12 thorpej putshort(p, l)
457 1.12 thorpej void *p;
458 1.12 thorpej unsigned short l;
459 1.12 thorpej {
460 1.12 thorpej unsigned char *cp = p;
461 1.12 thorpej
462 1.12 thorpej *cp++ = l;
463 1.12 thorpej *cp++ = l >> 8;
464 1.12 thorpej }
465 1.12 thorpej
466 1.12 thorpej static inline unsigned long
467 1.12 thorpej getlong(p)
468 1.12 thorpej void *p;
469 1.12 thorpej {
470 1.12 thorpej unsigned char *cp = p;
471 1.12 thorpej
472 1.12 thorpej return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
473 1.12 thorpej }
474 1.12 thorpej
475 1.12 thorpej static inline void
476 1.12 thorpej putlong(p, l)
477 1.12 thorpej void *p;
478 1.12 thorpej unsigned long l;
479 1.12 thorpej {
480 1.12 thorpej unsigned char *cp = p;
481 1.12 thorpej
482 1.12 thorpej *cp++ = l;
483 1.12 thorpej *cp++ = l >> 8;
484 1.12 thorpej *cp++ = l >> 16;
485 1.12 thorpej *cp++ = l >> 24;
486 1.12 thorpej }
487 1.4 mycroft
488 1.4 mycroft void
489 1.4 mycroft print_part(part)
490 1.1 cgd int part;
491 1.4 mycroft {
492 1.14 phil struct dos_partition *partp;
493 1.1 cgd int empty;
494 1.4 mycroft
495 1.14 phil partp = &mboot.parts[part];
496 1.14 phil empty = !memcmp(partp, &mtpart, sizeof(struct dos_partition));
497 1.15 phil
498 1.14 phil if (sh_flag) {
499 1.14 phil if (empty) {
500 1.14 phil printf("PART%dSIZE=0\n", part);
501 1.14 phil return;
502 1.14 phil }
503 1.14 phil
504 1.16 phil printf("PART%dID=%d\n", part, partp->dp_typ);
505 1.16 phil printf("PART%dSIZE=%ld\n", part, getlong(&partp->dp_size));
506 1.18 lukem printf("PART%dSTART=%ld\n", part, getlong(&partp->dp_start));
507 1.14 phil printf("PART%dFLAG=0x%x\n", part, partp->dp_flag);
508 1.14 phil printf("PART%dBCYL=%d\n", part, DPCYL(partp->dp_scyl,
509 1.14 phil partp->dp_ssect));
510 1.14 phil printf("PART%dBHEAD=%d\n", part, partp->dp_shd);
511 1.14 phil printf("PART%dBSEC=%d\n", part, DPSECT(partp->dp_ssect));
512 1.14 phil printf("PART%dECYL=%d\n", part, DPCYL(partp->dp_ecyl,
513 1.14 phil partp->dp_esect));
514 1.14 phil printf("PART%dEHEAD=%d\n", part, partp->dp_ehd);
515 1.14 phil printf("PART%dESEC=%d\n", part, DPSECT(partp->dp_esect));
516 1.14 phil return;
517 1.14 phil }
518 1.15 phil
519 1.14 phil /* Not sh_flag. */
520 1.1 cgd if (empty) {
521 1.1 cgd printf("<UNUSED>\n");
522 1.1 cgd return;
523 1.5 mycroft }
524 1.18 lukem printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
525 1.12 thorpej printf(" start %ld, size %ld (%ld MB), flag 0x%x\n",
526 1.12 thorpej getlong(&partp->dp_start), getlong(&partp->dp_size),
527 1.5 mycroft getlong(&partp->dp_size) * 512 / (1024 * 1024), partp->dp_flag);
528 1.5 mycroft printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
529 1.5 mycroft DPCYL(partp->dp_scyl, partp->dp_ssect),
530 1.5 mycroft partp->dp_shd, DPSECT(partp->dp_ssect));
531 1.5 mycroft printf("\tend: cylinder %4d, head %3d, sector %2d\n",
532 1.5 mycroft DPCYL(partp->dp_ecyl, partp->dp_esect),
533 1.1 cgd partp->dp_ehd, DPSECT(partp->dp_esect));
534 1.1 cgd }
535 1.4 mycroft
536 1.28 ws void
537 1.28 ws init_sector0(start, dopart)
538 1.1 cgd int start, dopart;
539 1.15 phil {
540 1.15 phil int i;
541 1.4 mycroft
542 1.12 thorpej memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
543 1.15 phil putshort(&mboot.signature, BOOT_MAGIC);
544 1.28 ws
545 1.28 ws if (dopart)
546 1.28 ws for (i=0; i<3; i++)
547 1.1 cgd memset (&mboot.parts[i], 0, sizeof(struct dos_partition));
548 1.11 ghudson
549 1.11 ghudson }
550 1.11 ghudson
551 1.11 ghudson /* Prerequisite: the disklabel parameters and master boot record must
552 1.11 ghudson * have been read (i.e. dos_* and mboot are meaningful).
553 1.11 ghudson * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
554 1.11 ghudson * dos_cylindersectors to be consistent with what the
555 1.11 ghudson * partition table is using, if we can find a geometry
556 1.11 ghudson * which is consistent with all partition table entries.
557 1.11 ghudson * We may get the number of cylinders slightly wrong (in
558 1.11 ghudson * the conservative direction). The idea is to be able
559 1.11 ghudson * to create a NetBSD partition on a disk we don't know
560 1.11 ghudson * the translated geometry of.
561 1.11 ghudson * This whole routine should be replaced with a kernel interface to get
562 1.11 ghudson * the BIOS geometry (which in turn requires modifications to the i386
563 1.11 ghudson * boot loader to pass in the BIOS geometry for each disk). */
564 1.11 ghudson void
565 1.11 ghudson intuit_translated_geometry()
566 1.15 phil {
567 1.11 ghudson
568 1.11 ghudson int cylinders = -1, heads = -1, sectors = -1, i, j;
569 1.11 ghudson int c1, h1, s1, c2, h2, s2;
570 1.11 ghudson long a1, a2;
571 1.11 ghudson quad_t num, denom;
572 1.11 ghudson
573 1.11 ghudson /* Try to deduce the number of heads from two different mappings. */
574 1.11 ghudson for (i = 0; i < NDOSPART * 2; i++) {
575 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
576 1.11 ghudson continue;
577 1.11 ghudson for (j = 0; j < 8; j++) {
578 1.11 ghudson if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
579 1.22 enami continue;
580 1.22 enami num = (quad_t)h1*(a2-s2) - (quad_t)h2*(a1-s1);
581 1.11 ghudson denom = (quad_t)c2*(a1-s1) - (quad_t)c1*(a2-s2);
582 1.11 ghudson if (denom != 0 && num % denom == 0) {
583 1.11 ghudson heads = num / denom;
584 1.11 ghudson break;
585 1.11 ghudson }
586 1.11 ghudson }
587 1.11 ghudson if (heads != -1)
588 1.11 ghudson break;
589 1.11 ghudson }
590 1.11 ghudson
591 1.11 ghudson if (heads == -1)
592 1.11 ghudson return;
593 1.11 ghudson
594 1.11 ghudson /* Now figure out the number of sectors from a single mapping. */
595 1.11 ghudson for (i = 0; i < NDOSPART * 2; i++) {
596 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
597 1.11 ghudson continue;
598 1.11 ghudson num = a1 - s1;
599 1.11 ghudson denom = c1 * heads + h1;
600 1.11 ghudson if (denom != 0 && num % denom == 0) {
601 1.11 ghudson sectors = num / denom;
602 1.11 ghudson break;
603 1.11 ghudson }
604 1.11 ghudson }
605 1.11 ghudson
606 1.11 ghudson if (sectors == -1)
607 1.11 ghudson return;
608 1.11 ghudson
609 1.24 ghudson /* Estimate the number of cylinders. */
610 1.11 ghudson cylinders = disklabel.d_secperunit / heads / sectors;
611 1.11 ghudson
612 1.11 ghudson /* Now verify consistency with each of the partition table entries.
613 1.11 ghudson * Be willing to shove cylinders up a little bit to make things work,
614 1.11 ghudson * but translation mismatches are fatal. */
615 1.11 ghudson for (i = 0; i < NDOSPART * 2; i++) {
616 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
617 1.11 ghudson continue;
618 1.11 ghudson if (sectors * (c1 * heads + h1) + s1 != a1)
619 1.11 ghudson return;
620 1.11 ghudson if (c1 >= cylinders)
621 1.11 ghudson cylinders = c1 + 1;
622 1.11 ghudson }
623 1.11 ghudson
624 1.11 ghudson /* Everything checks out. Reset the geometry to use for further
625 1.11 ghudson * calculations. */
626 1.11 ghudson dos_cylinders = cylinders;
627 1.11 ghudson dos_heads = heads;
628 1.11 ghudson dos_sectors = sectors;
629 1.11 ghudson dos_cylindersectors = heads * sectors;
630 1.11 ghudson }
631 1.11 ghudson
632 1.11 ghudson /* For the purposes of intuit_translated_geometry(), treat the partition
633 1.11 ghudson * table as a list of eight mapping between (cylinder, head, sector)
634 1.11 ghudson * triplets and absolute sectors. Get the relevant geometry triplet and
635 1.11 ghudson * absolute sectors for a given entry, or return -1 if it isn't present.
636 1.11 ghudson * Note: for simplicity, the returned sector is 0-based. */
637 1.11 ghudson int
638 1.11 ghudson get_mapping(i, cylinder, head, sector, absolute)
639 1.11 ghudson int i, *cylinder, *head, *sector;
640 1.11 ghudson long *absolute;
641 1.11 ghudson {
642 1.11 ghudson struct dos_partition *part = &mboot.parts[i / 2];
643 1.11 ghudson
644 1.11 ghudson if (part->dp_typ == 0)
645 1.11 ghudson return -1;
646 1.11 ghudson if (i % 2 == 0) {
647 1.11 ghudson *cylinder = DPCYL(part->dp_scyl, part->dp_ssect);
648 1.11 ghudson *head = part->dp_shd;
649 1.12 thorpej *sector = DPSECT(part->dp_ssect) - 1;
650 1.11 ghudson *absolute = getlong(&part->dp_start);
651 1.11 ghudson } else {
652 1.11 ghudson *cylinder = DPCYL(part->dp_ecyl, part->dp_esect);
653 1.11 ghudson *head = part->dp_ehd;
654 1.12 thorpej *sector = DPSECT(part->dp_esect) - 1;
655 1.12 thorpej *absolute = getlong(&part->dp_start)
656 1.11 ghudson + getlong(&part->dp_size) - 1;
657 1.11 ghudson }
658 1.1 cgd return 0;
659 1.1 cgd }
660 1.4 mycroft
661 1.15 phil void
662 1.15 phil change_part(part, csysid, cstart, csize)
663 1.1 cgd int part, csysid, cstart, csize;
664 1.4 mycroft {
665 1.1 cgd struct dos_partition *partp;
666 1.4 mycroft
667 1.1 cgd partp = &mboot.parts[part];
668 1.15 phil
669 1.29 ws if (s_flag) {
670 1.29 ws if (csysid == 0 && cstart == 0 && csize == 0)
671 1.29 ws memset(partp, 0, sizeof *partp);
672 1.29 ws else {
673 1.28 ws partp->dp_typ = csysid;
674 1.29 ws #if 0
675 1.28 ws checkcyl(cstart / dos_cylindersectors);
676 1.29 ws #endif
677 1.29 ws putlong(&partp->dp_start, cstart);
678 1.29 ws putlong(&partp->dp_size, csize);
679 1.29 ws dos(getlong(&partp->dp_start),
680 1.29 ws &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
681 1.29 ws dos(getlong(&partp->dp_start)
682 1.29 ws + getlong(&partp->dp_size) - 1,
683 1.29 ws &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
684 1.15 phil }
685 1.15 phil if (f_flag)
686 1.15 phil return;
687 1.15 phil }
688 1.15 phil
689 1.4 mycroft printf("The data for partition %d is:\n", part);
690 1.4 mycroft print_part(part);
691 1.4 mycroft if (!u_flag || !yesno("Do you want to change it?"))
692 1.1 cgd return;
693 1.1 cgd
694 1.5 mycroft do {
695 1.5 mycroft {
696 1.5 mycroft int sysid, start, size;
697 1.5 mycroft
698 1.12 thorpej sysid = partp->dp_typ,
699 1.12 thorpej start = getlong(&partp->dp_start),
700 1.5 mycroft size = getlong(&partp->dp_size);
701 1.5 mycroft decimal("sysid", &sysid);
702 1.5 mycroft decimal("start", &start);
703 1.5 mycroft decimal("size", &size);
704 1.12 thorpej partp->dp_typ = sysid;
705 1.12 thorpej putlong(&partp->dp_start, start);
706 1.5 mycroft putlong(&partp->dp_size, size);
707 1.1 cgd }
708 1.7 mycroft
709 1.5 mycroft if (yesno("Explicitly specify beg/end address?")) {
710 1.4 mycroft int tsector, tcylinder, thead;
711 1.5 mycroft
712 1.5 mycroft tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect);
713 1.5 mycroft thead = partp->dp_shd;
714 1.5 mycroft tsector = DPSECT(partp->dp_ssect);
715 1.28 ws decimal("beginning cylinder", &tcylinder);
716 1.28 ws #if 0
717 1.28 ws checkcyl(tcylinder);
718 1.5 mycroft #endif
719 1.5 mycroft decimal("beginning head", &thead);
720 1.5 mycroft decimal("beginning sector", &tsector);
721 1.5 mycroft partp->dp_scyl = DOSCYL(tcylinder);
722 1.5 mycroft partp->dp_shd = thead;
723 1.5 mycroft partp->dp_ssect = DOSSECT(tsector, tcylinder);
724 1.5 mycroft
725 1.5 mycroft tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect);
726 1.5 mycroft thead = partp->dp_ehd;
727 1.5 mycroft tsector = DPSECT(partp->dp_esect);
728 1.5 mycroft decimal("ending cylinder", &tcylinder);
729 1.5 mycroft decimal("ending head", &thead);
730 1.5 mycroft decimal("ending sector", &tsector);
731 1.5 mycroft partp->dp_ecyl = DOSCYL(tcylinder);
732 1.5 mycroft partp->dp_ehd = thead;
733 1.1 cgd partp->dp_esect = DOSSECT(tsector, tcylinder);
734 1.28 ws } else {
735 1.29 ws
736 1.29 ws if (partp->dp_typ == 0
737 1.29 ws && getlong(&partp->dp_start) == 0
738 1.29 ws && getlong(&partp->dp_size) == 0)
739 1.29 ws memset(partp, 0, sizeof *partp);
740 1.28 ws else {
741 1.29 ws #if 0
742 1.29 ws checkcyl(getlong(&partp->dp_start)
743 1.28 ws / dos_cylindersectors);
744 1.29 ws #endif
745 1.29 ws dos(getlong(&partp->dp_start), &partp->dp_scyl,
746 1.29 ws &partp->dp_shd, &partp->dp_ssect);
747 1.29 ws dos(getlong(&partp->dp_start)
748 1.29 ws + getlong(&partp->dp_size) - 1,
749 1.29 ws &partp->dp_ecyl, &partp->dp_ehd,
750 1.29 ws &partp->dp_esect);
751 1.1 cgd }
752 1.4 mycroft }
753 1.4 mycroft
754 1.7 mycroft print_part(part);
755 1.1 cgd } while (!yesno("Is this entry okay?"));
756 1.1 cgd }
757 1.4 mycroft
758 1.1 cgd void
759 1.1 cgd print_params()
760 1.4 mycroft {
761 1.15 phil
762 1.14 phil if (sh_flag) {
763 1.14 phil printf ("DLCYL=%d\nDLHEAD=%d\nDLSEC=%d\n",
764 1.14 phil cylinders, heads, sectors);
765 1.14 phil printf ("BCYL=%d\nBHEAD=%d\nBSEC=%d\n",
766 1.14 phil dos_cylinders, dos_heads, dos_sectors);
767 1.14 phil return;
768 1.14 phil }
769 1.15 phil
770 1.1 cgd /* Not sh_flag */
771 1.5 mycroft printf("parameters extracted from in-core disklabel are:\n");
772 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
773 1.28 ws cylinders, heads, sectors, cylindersectors);
774 1.5 mycroft if (dos_sectors > 63 || dos_heads > 255)
775 1.1 cgd printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
776 1.5 mycroft printf("parameters to be used for BIOS calculations are:\n");
777 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
778 1.1 cgd dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
779 1.1 cgd }
780 1.4 mycroft
781 1.1 cgd void
782 1.4 mycroft change_active(which)
783 1.1 cgd int which;
784 1.4 mycroft {
785 1.4 mycroft struct dos_partition *partp;
786 1.15 phil int part;
787 1.4 mycroft int active = 4;
788 1.4 mycroft
789 1.1 cgd partp = &mboot.parts[0];
790 1.1 cgd
791 1.1 cgd if (a_flag && which != -1)
792 1.4 mycroft active = which;
793 1.4 mycroft else {
794 1.4 mycroft for (part = 0; part < NDOSPART; part++)
795 1.4 mycroft if (partp[part].dp_flag & ACTIVE)
796 1.4 mycroft active = part;
797 1.15 phil }
798 1.15 phil if (!f_flag) {
799 1.15 phil if (yesno("Do you want to change the active partition?")) {
800 1.15 phil printf ("Choosing 4 will make no partition active.\n");
801 1.15 phil do {
802 1.15 phil decimal("active partition", &active);
803 1.15 phil } while (!yesno("Are you happy with this choice?"));
804 1.15 phil } else
805 1.15 phil return;
806 1.15 phil } else
807 1.15 phil if (active != 4)
808 1.15 phil printf ("Making partition %d active.\n", active);
809 1.4 mycroft
810 1.4 mycroft for (part = 0; part < NDOSPART; part++)
811 1.15 phil partp[part].dp_flag &= ~ACTIVE;
812 1.15 phil if (active < 4)
813 1.1 cgd partp[active].dp_flag |= ACTIVE;
814 1.1 cgd }
815 1.4 mycroft
816 1.1 cgd void
817 1.1 cgd get_params_to_use()
818 1.16 phil {
819 1.16 phil if (b_flag) {
820 1.16 phil dos_cylinders = b_cyl;
821 1.16 phil dos_heads = b_head;
822 1.16 phil dos_sectors = b_sec;
823 1.16 phil dos_cylindersectors = dos_heads * dos_sectors;
824 1.16 phil return;
825 1.4 mycroft }
826 1.1 cgd
827 1.4 mycroft print_params();
828 1.4 mycroft if (yesno("Do you want to change our idea of what BIOS thinks?")) {
829 1.5 mycroft do {
830 1.5 mycroft decimal("BIOS's idea of #cylinders", &dos_cylinders);
831 1.5 mycroft decimal("BIOS's idea of #heads", &dos_heads);
832 1.5 mycroft decimal("BIOS's idea of #sectors", &dos_sectors);
833 1.1 cgd dos_cylindersectors = dos_heads * dos_sectors;
834 1.4 mycroft print_params();
835 1.1 cgd } while (!yesno("Are you happy with this choice?"));
836 1.1 cgd }
837 1.1 cgd }
838 1.1 cgd
839 1.1 cgd /***********************************************\
840 1.1 cgd * Change real numbers into strange dos numbers *
841 1.4 mycroft \***********************************************/
842 1.5 mycroft void
843 1.5 mycroft dos(sector, cylinderp, headp, sectorp)
844 1.5 mycroft int sector;
845 1.4 mycroft unsigned char *cylinderp, *headp, *sectorp;
846 1.5 mycroft {
847 1.4 mycroft int cylinder, head;
848 1.5 mycroft
849 1.28 ws cylinder = sector / dos_cylindersectors;
850 1.5 mycroft
851 1.4 mycroft sector -= cylinder * dos_cylindersectors;
852 1.5 mycroft
853 1.5 mycroft head = sector / dos_sectors;
854 1.4 mycroft sector -= head * dos_sectors;
855 1.28 ws
856 1.28 ws if (cylinder >= MAXCYL)
857 1.5 mycroft cylinder = MAXCYL - 1;
858 1.5 mycroft *cylinderp = DOSCYL(cylinder);
859 1.5 mycroft *headp = head;
860 1.1 cgd *sectorp = DOSSECT(sector + 1, cylinder);
861 1.1 cgd }
862 1.28 ws
863 1.28 ws #if 0
864 1.28 ws void
865 1.28 ws checkcyl(cyl)
866 1.28 ws int cyl;
867 1.28 ws {
868 1.28 ws if (cyl >= MAXCYL)
869 1.28 ws warnx("partition start beyond BIOS limit");
870 1.28 ws }
871 1.28 ws #endif
872 1.1 cgd
873 1.1 cgd int fd;
874 1.4 mycroft
875 1.1 cgd int
876 1.4 mycroft open_disk(u_flag)
877 1.1 cgd int u_flag;
878 1.18 lukem {
879 1.4 mycroft static char namebuf[MAXPATHLEN + 1];
880 1.1 cgd struct stat st;
881 1.19 lukem
882 1.19 lukem fd = opendisk(disk, u_flag ? O_RDWR : O_RDONLY, namebuf,
883 1.18 lukem sizeof(namebuf), 0);
884 1.18 lukem if (fd < 0) {
885 1.4 mycroft warn("%s", namebuf);
886 1.4 mycroft return (-1);
887 1.18 lukem }
888 1.4 mycroft disk = namebuf;
889 1.4 mycroft if (fstat(fd, &st) == -1) {
890 1.4 mycroft close(fd);
891 1.4 mycroft warn("%s", disk);
892 1.1 cgd return (-1);
893 1.7 mycroft }
894 1.4 mycroft if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) {
895 1.7 mycroft close(fd);
896 1.4 mycroft warnx("%s is not a character device or regular file", disk);
897 1.1 cgd return (-1);
898 1.4 mycroft }
899 1.4 mycroft if (get_params() == -1) {
900 1.4 mycroft close(fd);
901 1.1 cgd return (-1);
902 1.4 mycroft }
903 1.1 cgd return (0);
904 1.1 cgd }
905 1.4 mycroft
906 1.1 cgd int
907 1.4 mycroft read_disk(sector, buf)
908 1.4 mycroft int sector;
909 1.1 cgd void *buf;
910 1.4 mycroft {
911 1.4 mycroft
912 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
913 1.4 mycroft return (-1);
914 1.1 cgd return (read(fd, buf, 512));
915 1.1 cgd }
916 1.4 mycroft
917 1.1 cgd int
918 1.4 mycroft write_disk(sector, buf)
919 1.4 mycroft int sector;
920 1.1 cgd void *buf;
921 1.4 mycroft {
922 1.4 mycroft
923 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
924 1.4 mycroft return (-1);
925 1.1 cgd return (write(fd, buf, 512));
926 1.1 cgd }
927 1.4 mycroft
928 1.4 mycroft int
929 1.1 cgd get_params()
930 1.1 cgd {
931 1.4 mycroft
932 1.4 mycroft if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
933 1.4 mycroft warn("DIOCGDINFO");
934 1.4 mycroft return (-1);
935 1.1 cgd }
936 1.5 mycroft
937 1.4 mycroft dos_cylinders = cylinders = disklabel.d_ncylinders;
938 1.4 mycroft dos_heads = heads = disklabel.d_ntracks;
939 1.5 mycroft dos_sectors = sectors = disklabel.d_nsectors;
940 1.5 mycroft dos_cylindersectors = cylindersectors = heads * sectors;
941 1.1 cgd disksectors = cylinders * heads * sectors;
942 1.4 mycroft
943 1.1 cgd return (0);
944 1.1 cgd }
945 1.4 mycroft
946 1.1 cgd int
947 1.1 cgd read_s0()
948 1.4 mycroft {
949 1.4 mycroft
950 1.4 mycroft if (read_disk(0, mboot.bootinst) == -1) {
951 1.4 mycroft warn("can't read fdisk partition table");
952 1.1 cgd return (-1);
953 1.12 thorpej }
954 1.12 thorpej if (getshort(&mboot.signature) != BOOT_MAGIC) {
955 1.4 mycroft warnx("invalid fdisk partition table found");
956 1.1 cgd return (-1);
957 1.4 mycroft }
958 1.1 cgd return (0);
959 1.1 cgd }
960 1.4 mycroft
961 1.1 cgd int
962 1.1 cgd write_s0()
963 1.4 mycroft {
964 1.4 mycroft int flag;
965 1.1 cgd
966 1.1 cgd /*
967 1.1 cgd * write enable label sector before write (if necessary),
968 1.1 cgd * disable after writing.
969 1.1 cgd * needed if the disklabel protected area also protects
970 1.1 cgd * sector 0. (e.g. empty disk)
971 1.1 cgd */
972 1.1 cgd flag = 1;
973 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
974 1.4 mycroft warn("DIOCWLABEL");
975 1.4 mycroft if (write_disk(0, mboot.bootinst) == -1) {
976 1.1 cgd warn("can't write fdisk partition table");
977 1.4 mycroft return -1;
978 1.1 cgd }
979 1.4 mycroft flag = 0;
980 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
981 1.16 phil warn("DIOCWLABEL");
982 1.1 cgd return 0;
983 1.1 cgd }
984 1.4 mycroft
985 1.4 mycroft int
986 1.4 mycroft yesno(str)
987 1.4 mycroft char *str;
988 1.4 mycroft {
989 1.1 cgd int ch, first;
990 1.1 cgd
991 1.1 cgd printf("%s [n] ", str);
992 1.4 mycroft
993 1.4 mycroft first = ch = getchar();
994 1.4 mycroft while (ch != '\n' && ch != EOF)
995 1.4 mycroft ch = getchar();
996 1.1 cgd return (first == 'y' || first == 'Y');
997 1.1 cgd }
998 1.5 mycroft
999 1.5 mycroft void
1000 1.4 mycroft decimal(str, num)
1001 1.5 mycroft char *str;
1002 1.1 cgd int *num;
1003 1.8 cgd {
1004 1.4 mycroft int acc = 0;
1005 1.1 cgd char *cp;
1006 1.5 mycroft
1007 1.5 mycroft for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
1008 1.1 cgd printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
1009 1.1 cgd
1010 1.7 mycroft fgets(lbuf, LBUF, stdin);
1011 1.7 mycroft lbuf[strlen(lbuf)-1] = '\0';
1012 1.7 mycroft cp = lbuf;
1013 1.7 mycroft
1014 1.7 mycroft cp += strspn(cp, " \t");
1015 1.5 mycroft if (*cp == '\0')
1016 1.1 cgd return;
1017 1.7 mycroft
1018 1.7 mycroft if (!isdigit(*cp))
1019 1.5 mycroft continue;
1020 1.7 mycroft acc = strtol(lbuf, &cp, 10);
1021 1.5 mycroft
1022 1.5 mycroft cp += strspn(cp, " \t");
1023 1.5 mycroft if (*cp != '\0')
1024 1.1 cgd continue;
1025 1.5 mycroft
1026 1.5 mycroft *num = acc;
1027 1.1 cgd return;
1028 1.1 cgd }
1029 1.1 cgd
1030 1.1 cgd }
1031 1.4 mycroft
1032 1.4 mycroft int
1033 1.4 mycroft type_match(key, item)
1034 1.4 mycroft const void *key, *item;
1035 1.4 mycroft {
1036 1.4 mycroft const int *typep = key;
1037 1.4 mycroft const struct part_type *ptr = item;
1038 1.4 mycroft
1039 1.4 mycroft if (*typep < ptr->type)
1040 1.4 mycroft return (-1);
1041 1.4 mycroft if (*typep > ptr->type)
1042 1.4 mycroft return (1);
1043 1.4 mycroft return (0);
1044 1.4 mycroft }
1045 1.4 mycroft
1046 1.4 mycroft char *
1047 1.4 mycroft get_type(type)
1048 1.4 mycroft int type;
1049 1.4 mycroft {
1050 1.4 mycroft struct part_type *ptr;
1051 1.4 mycroft
1052 1.4 mycroft ptr = bsearch(&type, part_types,
1053 1.4 mycroft sizeof(part_types) / sizeof(struct part_type),
1054 1.4 mycroft sizeof(struct part_type), type_match);
1055 1.4 mycroft if (ptr == 0)
1056 1.16 phil return ("unknown");
1057 1.1 cgd return (ptr->name);
1058 }
1059