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