fdisk.c revision 1.33 1 1.33 perry /* $NetBSD: fdisk.c,v 1.33 1999/02/09 19:11:46 perry 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.33 perry __RCSID("$NetBSD: fdisk.c,v 1.33 1999/02/09 19:11:46 perry 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.33 perry {0xe6, reserved},
217 1.25 drochner {0xeb, "BeOS"},
218 1.4 mycroft {0xF1, "SpeedStor or Storage Dimensions"},
219 1.25 drochner {0xF2, "DOS 3.3+ Secondary"},
220 1.25 drochner {0xf3, reserved},
221 1.25 drochner {0xF4, "SpeedStor large partition or Storage Dimensions"},
222 1.25 drochner {0xf6, reserved},
223 1.13 perry {0xFE, "SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML"},
224 1.1 cgd {0xFF, "Xenix Bad Block Table"},
225 1.1 cgd };
226 1.4 mycroft
227 1.4 mycroft void usage __P((void));
228 1.4 mycroft void print_s0 __P((int));
229 1.30 ws void print_part __P((int));
230 1.28 ws void read_boot __P((char *));
231 1.11 ghudson void init_sector0 __P((int, int));
232 1.11 ghudson void intuit_translated_geometry __P((void));
233 1.11 ghudson int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t,
234 1.11 ghudson quad_t));
235 1.15 phil int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t));
236 1.4 mycroft void change_part __P((int, int, int, int));
237 1.4 mycroft void print_params __P((void));
238 1.4 mycroft void change_active __P((int));
239 1.4 mycroft void get_params_to_use __P((void));
240 1.4 mycroft void dos __P((int, unsigned char *, unsigned char *, unsigned char *));
241 1.4 mycroft int open_disk __P((int));
242 1.4 mycroft int read_disk __P((int, void *));
243 1.4 mycroft int write_disk __P((int, void *));
244 1.4 mycroft int get_params __P((void));
245 1.4 mycroft int read_s0 __P((void));
246 1.4 mycroft int write_s0 __P((void));
247 1.5 mycroft int yesno __P((char *));
248 1.4 mycroft void decimal __P((char *, int *));
249 1.4 mycroft int type_match __P((const void *, const void *));
250 1.16 phil char *get_type __P((int));
251 1.16 phil int get_mapping __P((int, int *, int *, int *, long *));
252 1.16 phil
253 1.16 phil static inline unsigned short getshort __P((void *));
254 1.16 phil static inline void putshort __P((void *p, unsigned short));
255 1.16 phil static inline unsigned long getlong __P((void *));
256 1.16 phil static inline void putlong __P((void *, unsigned long));
257 1.16 phil
258 1.16 phil
259 1.1 cgd int main __P((int, char **));
260 1.4 mycroft
261 1.1 cgd int
262 1.4 mycroft main(argc, argv)
263 1.4 mycroft int argc;
264 1.1 cgd char *argv[];
265 1.4 mycroft {
266 1.4 mycroft int ch;
267 1.1 cgd int part;
268 1.15 phil
269 1.15 phil int csysid, cstart, csize; /* For the b_flag. */
270 1.16 phil
271 1.15 phil a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
272 1.30 ws csysid = cstart = csize = 0;
273 1.4 mycroft while ((ch = getopt(argc, argv, "0123Safius:b:c:")) != -1)
274 1.4 mycroft switch (ch) {
275 1.4 mycroft case '0':
276 1.4 mycroft partition = 0;
277 1.4 mycroft break;
278 1.4 mycroft case '1':
279 1.4 mycroft partition = 1;
280 1.4 mycroft break;
281 1.4 mycroft case '2':
282 1.4 mycroft partition = 2;
283 1.4 mycroft break;
284 1.4 mycroft case '3':
285 1.4 mycroft partition = 3;
286 1.15 phil break;
287 1.15 phil case 'S':
288 1.15 phil sh_flag = 1;
289 1.4 mycroft break;
290 1.4 mycroft case 'a':
291 1.4 mycroft a_flag = 1;
292 1.15 phil break;
293 1.15 phil case 'f':
294 1.15 phil f_flag = 1;
295 1.4 mycroft break;
296 1.4 mycroft case 'i':
297 1.15 phil i_flag = 1;
298 1.4 mycroft break;
299 1.4 mycroft case 'u':
300 1.1 cgd u_flag = 1;
301 1.14 phil break;
302 1.14 phil case 's':
303 1.16 phil s_flag = 1;
304 1.16 phil if (sscanf (optarg, "%d/%d/%d",
305 1.16 phil &csysid, &cstart, &csize) != 3) {
306 1.16 phil (void)fprintf (stderr, "%s: Bad argument "
307 1.16 phil "to the -s flag.\n",
308 1.16 phil argv[0]);
309 1.16 phil exit (1);
310 1.16 phil }
311 1.16 phil break;
312 1.16 phil case 'b':
313 1.16 phil b_flag = 1;
314 1.16 phil if (sscanf (optarg, "%d/%d/%d",
315 1.16 phil &b_cyl, &b_head, &b_sec) != 3) {
316 1.16 phil (void)fprintf (stderr, "%s: Bad argument "
317 1.16 phil "to the -b flag.\n",
318 1.16 phil argv[0]);
319 1.16 phil exit (1);
320 1.28 ws }
321 1.28 ws if (b_cyl > MAXCYL)
322 1.14 phil b_cyl = MAXCYL;
323 1.30 ws break;
324 1.30 ws case 'c':
325 1.30 ws read_boot(optarg);
326 1.4 mycroft break;
327 1.4 mycroft default:
328 1.1 cgd usage();
329 1.4 mycroft }
330 1.4 mycroft argc -= optind;
331 1.1 cgd argv += optind;
332 1.15 phil
333 1.15 phil if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
334 1.15 phil usage();
335 1.15 phil
336 1.15 phil if (partition == -1 && s_flag) {
337 1.15 phil (void) fprintf (stderr,
338 1.14 phil "-s flag requires a partition selected.\n");
339 1.15 phil usage();
340 1.15 phil }
341 1.1 cgd
342 1.1 cgd if (argc > 0)
343 1.4 mycroft disk = argv[0];
344 1.4 mycroft
345 1.1 cgd if (open_disk(a_flag || i_flag || u_flag) < 0)
346 1.1 cgd exit(1);
347 1.11 ghudson
348 1.28 ws if (read_s0())
349 1.11 ghudson init_sector0(sectors > 63 ? 63 : sectors, 1);
350 1.11 ghudson
351 1.11 ghudson intuit_translated_geometry();
352 1.17 phil
353 1.14 phil if (!sh_flag && !f_flag)
354 1.15 phil printf("******* Working on device %s *******\n", disk);
355 1.15 phil
356 1.16 phil
357 1.1 cgd if ((i_flag || u_flag) && (!f_flag || b_flag))
358 1.1 cgd get_params_to_use();
359 1.15 phil
360 1.28 ws if (i_flag)
361 1.15 phil init_sector0(dos_sectors > 63 ? 63 : dos_sectors, 0);
362 1.17 phil
363 1.14 phil if (!sh_flag && !f_flag)
364 1.14 phil printf("Warning: BIOS sector numbering starts with sector 1\n");
365 1.15 phil
366 1.15 phil /* Do the update stuff! */
367 1.15 phil if (u_flag) {
368 1.15 phil if (!f_flag)
369 1.15 phil printf("Information from DOS bootblock is:\n");
370 1.32 thorpej if (partition == -1)
371 1.15 phil for (part = 0; part < NMBRPART; part++)
372 1.15 phil change_part(part,-1, -1, -1);
373 1.15 phil else
374 1.4 mycroft change_part(partition, csysid, cstart, csize);
375 1.15 phil } else
376 1.15 phil if (!i_flag)
377 1.1 cgd print_s0(partition);
378 1.15 phil
379 1.1 cgd if (a_flag)
380 1.1 cgd change_active(partition);
381 1.15 phil
382 1.15 phil if (u_flag || a_flag || i_flag) {
383 1.15 phil if (!f_flag) {
384 1.15 phil printf("\nWe haven't changed the partition table "
385 1.15 phil "yet. This is your last chance.\n");
386 1.15 phil print_s0(-1);
387 1.15 phil if (yesno("Should we write new partition table?"))
388 1.15 phil write_s0();
389 1.1 cgd } else
390 1.1 cgd write_s0();
391 1.1 cgd }
392 1.1 cgd
393 1.4 mycroft exit(0);
394 1.1 cgd }
395 1.4 mycroft
396 1.4 mycroft void
397 1.4 mycroft usage()
398 1.30 ws {
399 1.16 phil (void)fprintf(stderr, "usage: fdisk [-aiufSc] [-0|-1|-2|-3] "
400 1.4 mycroft "[device]\n");
401 1.1 cgd exit(1);
402 1.1 cgd }
403 1.4 mycroft
404 1.1 cgd void
405 1.4 mycroft print_s0(which)
406 1.1 cgd int which;
407 1.4 mycroft {
408 1.1 cgd int part;
409 1.1 cgd
410 1.15 phil print_params();
411 1.15 phil if (!sh_flag)
412 1.4 mycroft printf("Information from DOS bootblock is:\n");
413 1.32 thorpej if (which == -1) {
414 1.15 phil for (part = 0; part < NMBRPART; part++) {
415 1.15 phil if (!sh_flag)
416 1.15 phil printf("%d: ", part);
417 1.15 phil print_part(part);
418 1.4 mycroft }
419 1.1 cgd } else
420 1.1 cgd print_part(which);
421 1.1 cgd }
422 1.32 thorpej
423 1.1 cgd static struct mbr_partition mtpart = { 0 };
424 1.12 thorpej
425 1.12 thorpej static inline unsigned short
426 1.12 thorpej getshort(p)
427 1.12 thorpej void *p;
428 1.12 thorpej {
429 1.12 thorpej unsigned char *cp = p;
430 1.12 thorpej
431 1.12 thorpej return cp[0] | (cp[1] << 8);
432 1.12 thorpej }
433 1.12 thorpej
434 1.12 thorpej static inline void
435 1.12 thorpej putshort(p, l)
436 1.12 thorpej void *p;
437 1.12 thorpej unsigned short l;
438 1.12 thorpej {
439 1.12 thorpej unsigned char *cp = p;
440 1.12 thorpej
441 1.12 thorpej *cp++ = l;
442 1.12 thorpej *cp++ = l >> 8;
443 1.12 thorpej }
444 1.12 thorpej
445 1.12 thorpej static inline unsigned long
446 1.12 thorpej getlong(p)
447 1.12 thorpej void *p;
448 1.12 thorpej {
449 1.12 thorpej unsigned char *cp = p;
450 1.12 thorpej
451 1.12 thorpej return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
452 1.12 thorpej }
453 1.12 thorpej
454 1.12 thorpej static inline void
455 1.12 thorpej putlong(p, l)
456 1.12 thorpej void *p;
457 1.12 thorpej unsigned long l;
458 1.12 thorpej {
459 1.12 thorpej unsigned char *cp = p;
460 1.12 thorpej
461 1.12 thorpej *cp++ = l;
462 1.12 thorpej *cp++ = l >> 8;
463 1.12 thorpej *cp++ = l >> 16;
464 1.12 thorpej *cp++ = l >> 24;
465 1.12 thorpej }
466 1.4 mycroft
467 1.4 mycroft void
468 1.4 mycroft print_part(part)
469 1.1 cgd int part;
470 1.32 thorpej {
471 1.14 phil struct mbr_partition *partp;
472 1.1 cgd int empty;
473 1.4 mycroft
474 1.32 thorpej partp = &mboot.parts[part];
475 1.14 phil empty = !memcmp(partp, &mtpart, sizeof(struct mbr_partition));
476 1.15 phil
477 1.14 phil if (sh_flag) {
478 1.14 phil if (empty) {
479 1.14 phil printf("PART%dSIZE=0\n", part);
480 1.14 phil return;
481 1.14 phil }
482 1.32 thorpej
483 1.32 thorpej printf("PART%dID=%d\n", part, partp->mbrp_typ);
484 1.32 thorpej printf("PART%dSIZE=%ld\n", part, getlong(&partp->mbrp_size));
485 1.32 thorpej printf("PART%dSTART=%ld\n", part, getlong(&partp->mbrp_start));
486 1.32 thorpej printf("PART%dFLAG=0x%x\n", part, partp->mbrp_flag);
487 1.32 thorpej printf("PART%dBCYL=%d\n", part, MBR_PCYL(partp->mbrp_scyl,
488 1.32 thorpej partp->mbrp_ssect));
489 1.32 thorpej printf("PART%dBHEAD=%d\n", part, partp->mbrp_shd);
490 1.32 thorpej printf("PART%dBSEC=%d\n", part, MBR_PSECT(partp->mbrp_ssect));
491 1.32 thorpej printf("PART%dECYL=%d\n", part, MBR_PCYL(partp->mbrp_ecyl,
492 1.32 thorpej partp->mbrp_esect));
493 1.32 thorpej printf("PART%dEHEAD=%d\n", part, partp->mbrp_ehd);
494 1.14 phil printf("PART%dESEC=%d\n", part, MBR_PSECT(partp->mbrp_esect));
495 1.14 phil return;
496 1.14 phil }
497 1.15 phil
498 1.14 phil /* Not sh_flag. */
499 1.1 cgd if (empty) {
500 1.1 cgd printf("<UNUSED>\n");
501 1.1 cgd return;
502 1.32 thorpej }
503 1.18 lukem printf("sysid %d (%s)\n", partp->mbrp_typ, get_type(partp->mbrp_typ));
504 1.32 thorpej printf(" start %ld, size %ld (%ld MB), flag 0x%x\n",
505 1.32 thorpej getlong(&partp->mbrp_start), getlong(&partp->mbrp_size),
506 1.5 mycroft getlong(&partp->mbrp_size) * 512 / (1024 * 1024), partp->mbrp_flag);
507 1.32 thorpej printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
508 1.32 thorpej MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect),
509 1.5 mycroft partp->mbrp_shd, MBR_PSECT(partp->mbrp_ssect));
510 1.32 thorpej printf("\tend: cylinder %4d, head %3d, sector %2d\n",
511 1.32 thorpej MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect),
512 1.1 cgd partp->mbrp_ehd, MBR_PSECT(partp->mbrp_esect));
513 1.1 cgd }
514 1.4 mycroft
515 1.30 ws void
516 1.30 ws read_boot(name)
517 1.30 ws char *name;
518 1.30 ws {
519 1.30 ws int fd;
520 1.30 ws struct stat st;
521 1.30 ws
522 1.30 ws if ((fd = open(name, O_RDONLY)) < 0)
523 1.30 ws err(1, "%s", name);
524 1.30 ws if (fstat(fd, &st) == -1)
525 1.30 ws err(1, "%s", name);
526 1.30 ws if (st.st_size > sizeof(bootcode))
527 1.30 ws errx(1, "%s: bootcode too large", name);
528 1.30 ws bootsize = st.st_size;
529 1.30 ws if (bootsize < 0x200)
530 1.30 ws errx(1, "%s: bootcode too small", name);
531 1.30 ws if (read(fd, bootcode, bootsize) != bootsize)
532 1.30 ws err(1, "%s", name);
533 1.30 ws close(fd);
534 1.30 ws
535 1.30 ws /*
536 1.30 ws * Do some sanity checking here
537 1.32 thorpej */
538 1.30 ws if (getshort(bootcode + MBR_MAGICOFF) != MBR_MAGIC)
539 1.30 ws errx(1, "%s: invalid magic", name);
540 1.30 ws bootsize = (bootsize + 0x1ff) / 0x200;
541 1.30 ws bootsize *= 0x200;
542 1.30 ws }
543 1.30 ws
544 1.28 ws void
545 1.28 ws init_sector0(start, dopart)
546 1.1 cgd int start, dopart;
547 1.15 phil {
548 1.15 phil int i;
549 1.30 ws
550 1.30 ws #ifdef DEFAULT_BOOTCODE
551 1.30 ws if (!bootsize)
552 1.30 ws read_boot(DEFAULT_BOOTCODE);
553 1.30 ws #endif
554 1.30 ws
555 1.32 thorpej memcpy(mboot.bootinst, bootcode, sizeof(mboot.bootinst));
556 1.15 phil putshort(&mboot.signature, MBR_MAGIC);
557 1.28 ws
558 1.28 ws if (dopart)
559 1.32 thorpej for (i=0; i<3; i++)
560 1.1 cgd memset (&mboot.parts[i], 0, sizeof(struct mbr_partition));
561 1.11 ghudson
562 1.11 ghudson }
563 1.11 ghudson
564 1.11 ghudson /* Prerequisite: the disklabel parameters and master boot record must
565 1.11 ghudson * have been read (i.e. dos_* and mboot are meaningful).
566 1.11 ghudson * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
567 1.11 ghudson * dos_cylindersectors to be consistent with what the
568 1.11 ghudson * partition table is using, if we can find a geometry
569 1.11 ghudson * which is consistent with all partition table entries.
570 1.11 ghudson * We may get the number of cylinders slightly wrong (in
571 1.11 ghudson * the conservative direction). The idea is to be able
572 1.11 ghudson * to create a NetBSD partition on a disk we don't know
573 1.11 ghudson * the translated geometry of.
574 1.11 ghudson * This whole routine should be replaced with a kernel interface to get
575 1.11 ghudson * the BIOS geometry (which in turn requires modifications to the i386
576 1.11 ghudson * boot loader to pass in the BIOS geometry for each disk). */
577 1.11 ghudson void
578 1.11 ghudson intuit_translated_geometry()
579 1.15 phil {
580 1.11 ghudson
581 1.11 ghudson int cylinders = -1, heads = -1, sectors = -1, i, j;
582 1.11 ghudson int c1, h1, s1, c2, h2, s2;
583 1.11 ghudson long a1, a2;
584 1.11 ghudson quad_t num, denom;
585 1.11 ghudson
586 1.32 thorpej /* Try to deduce the number of heads from two different mappings. */
587 1.11 ghudson for (i = 0; i < NMBRPART * 2; i++) {
588 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
589 1.11 ghudson continue;
590 1.11 ghudson for (j = 0; j < 8; j++) {
591 1.11 ghudson if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
592 1.22 enami continue;
593 1.22 enami num = (quad_t)h1*(a2-s2) - (quad_t)h2*(a1-s1);
594 1.11 ghudson denom = (quad_t)c2*(a1-s1) - (quad_t)c1*(a2-s2);
595 1.11 ghudson if (denom != 0 && num % denom == 0) {
596 1.11 ghudson heads = num / denom;
597 1.11 ghudson break;
598 1.11 ghudson }
599 1.11 ghudson }
600 1.11 ghudson if (heads != -1)
601 1.11 ghudson break;
602 1.11 ghudson }
603 1.11 ghudson
604 1.11 ghudson if (heads == -1)
605 1.11 ghudson return;
606 1.11 ghudson
607 1.32 thorpej /* Now figure out the number of sectors from a single mapping. */
608 1.11 ghudson for (i = 0; i < NMBRPART * 2; i++) {
609 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
610 1.11 ghudson continue;
611 1.11 ghudson num = a1 - s1;
612 1.11 ghudson denom = c1 * heads + h1;
613 1.11 ghudson if (denom != 0 && num % denom == 0) {
614 1.11 ghudson sectors = num / denom;
615 1.11 ghudson break;
616 1.11 ghudson }
617 1.11 ghudson }
618 1.11 ghudson
619 1.11 ghudson if (sectors == -1)
620 1.11 ghudson return;
621 1.11 ghudson
622 1.24 ghudson /* Estimate the number of cylinders. */
623 1.11 ghudson cylinders = disklabel.d_secperunit / heads / sectors;
624 1.11 ghudson
625 1.11 ghudson /* Now verify consistency with each of the partition table entries.
626 1.11 ghudson * Be willing to shove cylinders up a little bit to make things work,
627 1.32 thorpej * but translation mismatches are fatal. */
628 1.11 ghudson for (i = 0; i < NMBRPART * 2; i++) {
629 1.11 ghudson if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
630 1.11 ghudson continue;
631 1.11 ghudson if (sectors * (c1 * heads + h1) + s1 != a1)
632 1.11 ghudson return;
633 1.11 ghudson if (c1 >= cylinders)
634 1.11 ghudson cylinders = c1 + 1;
635 1.11 ghudson }
636 1.11 ghudson
637 1.11 ghudson /* Everything checks out. Reset the geometry to use for further
638 1.11 ghudson * calculations. */
639 1.11 ghudson dos_cylinders = cylinders;
640 1.11 ghudson dos_heads = heads;
641 1.11 ghudson dos_sectors = sectors;
642 1.11 ghudson dos_cylindersectors = heads * sectors;
643 1.11 ghudson }
644 1.11 ghudson
645 1.11 ghudson /* For the purposes of intuit_translated_geometry(), treat the partition
646 1.11 ghudson * table as a list of eight mapping between (cylinder, head, sector)
647 1.11 ghudson * triplets and absolute sectors. Get the relevant geometry triplet and
648 1.11 ghudson * absolute sectors for a given entry, or return -1 if it isn't present.
649 1.11 ghudson * Note: for simplicity, the returned sector is 0-based. */
650 1.11 ghudson int
651 1.11 ghudson get_mapping(i, cylinder, head, sector, absolute)
652 1.11 ghudson int i, *cylinder, *head, *sector;
653 1.11 ghudson long *absolute;
654 1.32 thorpej {
655 1.11 ghudson struct mbr_partition *part = &mboot.parts[i / 2];
656 1.32 thorpej
657 1.11 ghudson if (part->mbrp_typ == 0)
658 1.11 ghudson return -1;
659 1.32 thorpej if (i % 2 == 0) {
660 1.32 thorpej *cylinder = MBR_PCYL(part->mbrp_scyl, part->mbrp_ssect);
661 1.32 thorpej *head = part->mbrp_shd;
662 1.32 thorpej *sector = MBR_PSECT(part->mbrp_ssect) - 1;
663 1.11 ghudson *absolute = getlong(&part->mbrp_start);
664 1.32 thorpej } else {
665 1.32 thorpej *cylinder = MBR_PCYL(part->mbrp_ecyl, part->mbrp_esect);
666 1.32 thorpej *head = part->mbrp_ehd;
667 1.32 thorpej *sector = MBR_PSECT(part->mbrp_esect) - 1;
668 1.32 thorpej *absolute = getlong(&part->mbrp_start)
669 1.11 ghudson + getlong(&part->mbrp_size) - 1;
670 1.11 ghudson }
671 1.1 cgd return 0;
672 1.1 cgd }
673 1.4 mycroft
674 1.15 phil void
675 1.15 phil change_part(part, csysid, cstart, csize)
676 1.1 cgd int part, csysid, cstart, csize;
677 1.32 thorpej {
678 1.1 cgd struct mbr_partition *partp;
679 1.4 mycroft
680 1.1 cgd partp = &mboot.parts[part];
681 1.15 phil
682 1.29 ws if (s_flag) {
683 1.29 ws if (csysid == 0 && cstart == 0 && csize == 0)
684 1.29 ws memset(partp, 0, sizeof *partp);
685 1.32 thorpej else {
686 1.28 ws partp->mbrp_typ = csysid;
687 1.29 ws #if 0
688 1.28 ws checkcyl(cstart / dos_cylindersectors);
689 1.32 thorpej #endif
690 1.32 thorpej putlong(&partp->mbrp_start, cstart);
691 1.32 thorpej putlong(&partp->mbrp_size, csize);
692 1.32 thorpej dos(getlong(&partp->mbrp_start),
693 1.32 thorpej &partp->mbrp_scyl, &partp->mbrp_shd, &partp->mbrp_ssect);
694 1.32 thorpej dos(getlong(&partp->mbrp_start)
695 1.32 thorpej + getlong(&partp->mbrp_size) - 1,
696 1.29 ws &partp->mbrp_ecyl, &partp->mbrp_ehd, &partp->mbrp_esect);
697 1.15 phil }
698 1.15 phil if (f_flag)
699 1.15 phil return;
700 1.15 phil }
701 1.15 phil
702 1.4 mycroft printf("The data for partition %d is:\n", part);
703 1.4 mycroft print_part(part);
704 1.4 mycroft if (!u_flag || !yesno("Do you want to change it?"))
705 1.1 cgd return;
706 1.1 cgd
707 1.5 mycroft do {
708 1.5 mycroft {
709 1.5 mycroft int sysid, start, size;
710 1.32 thorpej
711 1.32 thorpej sysid = partp->mbrp_typ,
712 1.32 thorpej start = getlong(&partp->mbrp_start),
713 1.5 mycroft size = getlong(&partp->mbrp_size);
714 1.5 mycroft decimal("sysid", &sysid);
715 1.5 mycroft decimal("start", &start);
716 1.32 thorpej decimal("size", &size);
717 1.32 thorpej partp->mbrp_typ = sysid;
718 1.32 thorpej putlong(&partp->mbrp_start, start);
719 1.5 mycroft putlong(&partp->mbrp_size, size);
720 1.1 cgd }
721 1.7 mycroft
722 1.5 mycroft if (yesno("Explicitly specify beg/end address?")) {
723 1.4 mycroft int tsector, tcylinder, thead;
724 1.32 thorpej
725 1.32 thorpej tcylinder = MBR_PCYL(partp->mbrp_scyl, partp->mbrp_ssect);
726 1.32 thorpej thead = partp->mbrp_shd;
727 1.5 mycroft tsector = MBR_PSECT(partp->mbrp_ssect);
728 1.28 ws decimal("beginning cylinder", &tcylinder);
729 1.28 ws #if 0
730 1.28 ws checkcyl(tcylinder);
731 1.5 mycroft #endif
732 1.5 mycroft decimal("beginning head", &thead);
733 1.32 thorpej decimal("beginning sector", &tsector);
734 1.32 thorpej partp->mbrp_scyl = DOSCYL(tcylinder);
735 1.32 thorpej partp->mbrp_shd = thead;
736 1.32 thorpej partp->mbrp_ssect = DOSSECT(tsector, tcylinder);
737 1.32 thorpej
738 1.32 thorpej tcylinder = MBR_PCYL(partp->mbrp_ecyl, partp->mbrp_esect);
739 1.32 thorpej thead = partp->mbrp_ehd;
740 1.5 mycroft tsector = MBR_PSECT(partp->mbrp_esect);
741 1.5 mycroft decimal("ending cylinder", &tcylinder);
742 1.5 mycroft decimal("ending head", &thead);
743 1.32 thorpej decimal("ending sector", &tsector);
744 1.32 thorpej partp->mbrp_ecyl = DOSCYL(tcylinder);
745 1.32 thorpej partp->mbrp_ehd = thead;
746 1.1 cgd partp->mbrp_esect = DOSSECT(tsector, tcylinder);
747 1.28 ws } else {
748 1.32 thorpej
749 1.32 thorpej if (partp->mbrp_typ == 0
750 1.32 thorpej && getlong(&partp->mbrp_start) == 0
751 1.29 ws && getlong(&partp->mbrp_size) == 0)
752 1.29 ws memset(partp, 0, sizeof *partp);
753 1.28 ws else {
754 1.32 thorpej #if 0
755 1.29 ws checkcyl(getlong(&partp->mbrp_start)
756 1.28 ws / dos_cylindersectors);
757 1.32 thorpej #endif
758 1.32 thorpej dos(getlong(&partp->mbrp_start), &partp->mbrp_scyl,
759 1.32 thorpej &partp->mbrp_shd, &partp->mbrp_ssect);
760 1.32 thorpej dos(getlong(&partp->mbrp_start)
761 1.32 thorpej + getlong(&partp->mbrp_size) - 1,
762 1.32 thorpej &partp->mbrp_ecyl, &partp->mbrp_ehd,
763 1.29 ws &partp->mbrp_esect);
764 1.1 cgd }
765 1.4 mycroft }
766 1.4 mycroft
767 1.7 mycroft print_part(part);
768 1.1 cgd } while (!yesno("Is this entry okay?"));
769 1.1 cgd }
770 1.4 mycroft
771 1.1 cgd void
772 1.1 cgd print_params()
773 1.4 mycroft {
774 1.15 phil
775 1.31 jonathan if (sh_flag) {
776 1.31 jonathan printf ("DLCYL=%d\nDLHEAD=%d\nDLSEC=%d\nDLSIZE=%d\n",
777 1.14 phil cylinders, heads, sectors, disksectors);
778 1.14 phil printf ("BCYL=%d\nBHEAD=%d\nBSEC=%d\n",
779 1.14 phil dos_cylinders, dos_heads, dos_sectors);
780 1.14 phil return;
781 1.14 phil }
782 1.15 phil
783 1.1 cgd /* Not sh_flag */
784 1.5 mycroft printf("parameters extracted from in-core disklabel are:\n");
785 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
786 1.28 ws cylinders, heads, sectors, cylindersectors);
787 1.5 mycroft if (dos_sectors > 63 || dos_heads > 255)
788 1.1 cgd printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
789 1.5 mycroft printf("parameters to be used for BIOS calculations are:\n");
790 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
791 1.1 cgd dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
792 1.1 cgd }
793 1.4 mycroft
794 1.1 cgd void
795 1.4 mycroft change_active(which)
796 1.1 cgd int which;
797 1.32 thorpej {
798 1.4 mycroft struct mbr_partition *partp;
799 1.15 phil int part;
800 1.4 mycroft int active = 4;
801 1.4 mycroft
802 1.1 cgd partp = &mboot.parts[0];
803 1.1 cgd
804 1.1 cgd if (a_flag && which != -1)
805 1.4 mycroft active = which;
806 1.32 thorpej else {
807 1.32 thorpej for (part = 0; part < NMBRPART; part++)
808 1.4 mycroft if (partp[part].mbrp_flag & ACTIVE)
809 1.4 mycroft active = part;
810 1.15 phil }
811 1.15 phil if (!f_flag) {
812 1.15 phil if (yesno("Do you want to change the active partition?")) {
813 1.15 phil printf ("Choosing 4 will make no partition active.\n");
814 1.15 phil do {
815 1.15 phil decimal("active partition", &active);
816 1.15 phil } while (!yesno("Are you happy with this choice?"));
817 1.15 phil } else
818 1.15 phil return;
819 1.15 phil } else
820 1.15 phil if (active != 4)
821 1.15 phil printf ("Making partition %d active.\n", active);
822 1.32 thorpej
823 1.32 thorpej for (part = 0; part < NMBRPART; part++)
824 1.15 phil partp[part].mbrp_flag &= ~ACTIVE;
825 1.32 thorpej if (active < 4)
826 1.1 cgd partp[active].mbrp_flag |= ACTIVE;
827 1.1 cgd }
828 1.4 mycroft
829 1.1 cgd void
830 1.1 cgd get_params_to_use()
831 1.16 phil {
832 1.16 phil if (b_flag) {
833 1.16 phil dos_cylinders = b_cyl;
834 1.16 phil dos_heads = b_head;
835 1.16 phil dos_sectors = b_sec;
836 1.16 phil dos_cylindersectors = dos_heads * dos_sectors;
837 1.16 phil return;
838 1.4 mycroft }
839 1.1 cgd
840 1.4 mycroft print_params();
841 1.4 mycroft if (yesno("Do you want to change our idea of what BIOS thinks?")) {
842 1.5 mycroft do {
843 1.5 mycroft decimal("BIOS's idea of #cylinders", &dos_cylinders);
844 1.5 mycroft decimal("BIOS's idea of #heads", &dos_heads);
845 1.5 mycroft decimal("BIOS's idea of #sectors", &dos_sectors);
846 1.1 cgd dos_cylindersectors = dos_heads * dos_sectors;
847 1.4 mycroft print_params();
848 1.1 cgd } while (!yesno("Are you happy with this choice?"));
849 1.1 cgd }
850 1.1 cgd }
851 1.1 cgd
852 1.1 cgd /***********************************************\
853 1.1 cgd * Change real numbers into strange dos numbers *
854 1.4 mycroft \***********************************************/
855 1.5 mycroft void
856 1.5 mycroft dos(sector, cylinderp, headp, sectorp)
857 1.5 mycroft int sector;
858 1.4 mycroft unsigned char *cylinderp, *headp, *sectorp;
859 1.5 mycroft {
860 1.4 mycroft int cylinder, head;
861 1.5 mycroft
862 1.28 ws cylinder = sector / dos_cylindersectors;
863 1.5 mycroft
864 1.4 mycroft sector -= cylinder * dos_cylindersectors;
865 1.5 mycroft
866 1.5 mycroft head = sector / dos_sectors;
867 1.4 mycroft sector -= head * dos_sectors;
868 1.28 ws
869 1.28 ws if (cylinder >= MAXCYL)
870 1.5 mycroft cylinder = MAXCYL - 1;
871 1.5 mycroft *cylinderp = DOSCYL(cylinder);
872 1.5 mycroft *headp = head;
873 1.1 cgd *sectorp = DOSSECT(sector + 1, cylinder);
874 1.1 cgd }
875 1.28 ws
876 1.28 ws #if 0
877 1.28 ws void
878 1.28 ws checkcyl(cyl)
879 1.28 ws int cyl;
880 1.28 ws {
881 1.28 ws if (cyl >= MAXCYL)
882 1.28 ws warnx("partition start beyond BIOS limit");
883 1.28 ws }
884 1.28 ws #endif
885 1.1 cgd
886 1.1 cgd int fd;
887 1.4 mycroft
888 1.1 cgd int
889 1.4 mycroft open_disk(u_flag)
890 1.1 cgd int u_flag;
891 1.18 lukem {
892 1.4 mycroft static char namebuf[MAXPATHLEN + 1];
893 1.1 cgd struct stat st;
894 1.19 lukem
895 1.19 lukem fd = opendisk(disk, u_flag ? O_RDWR : O_RDONLY, namebuf,
896 1.18 lukem sizeof(namebuf), 0);
897 1.18 lukem if (fd < 0) {
898 1.4 mycroft warn("%s", namebuf);
899 1.4 mycroft return (-1);
900 1.18 lukem }
901 1.4 mycroft disk = namebuf;
902 1.4 mycroft if (fstat(fd, &st) == -1) {
903 1.4 mycroft close(fd);
904 1.4 mycroft warn("%s", disk);
905 1.1 cgd return (-1);
906 1.7 mycroft }
907 1.4 mycroft if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) {
908 1.7 mycroft close(fd);
909 1.4 mycroft warnx("%s is not a character device or regular file", disk);
910 1.1 cgd return (-1);
911 1.4 mycroft }
912 1.4 mycroft if (get_params() == -1) {
913 1.4 mycroft close(fd);
914 1.1 cgd return (-1);
915 1.4 mycroft }
916 1.1 cgd return (0);
917 1.1 cgd }
918 1.4 mycroft
919 1.1 cgd int
920 1.4 mycroft read_disk(sector, buf)
921 1.4 mycroft int sector;
922 1.1 cgd void *buf;
923 1.4 mycroft {
924 1.4 mycroft
925 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
926 1.4 mycroft return (-1);
927 1.1 cgd return (read(fd, buf, 512));
928 1.1 cgd }
929 1.4 mycroft
930 1.1 cgd int
931 1.4 mycroft write_disk(sector, buf)
932 1.4 mycroft int sector;
933 1.1 cgd void *buf;
934 1.4 mycroft {
935 1.4 mycroft
936 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
937 1.4 mycroft return (-1);
938 1.1 cgd return (write(fd, buf, 512));
939 1.1 cgd }
940 1.4 mycroft
941 1.4 mycroft int
942 1.1 cgd get_params()
943 1.1 cgd {
944 1.4 mycroft
945 1.4 mycroft if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
946 1.4 mycroft warn("DIOCGDINFO");
947 1.4 mycroft return (-1);
948 1.1 cgd }
949 1.5 mycroft
950 1.4 mycroft dos_cylinders = cylinders = disklabel.d_ncylinders;
951 1.4 mycroft dos_heads = heads = disklabel.d_ntracks;
952 1.5 mycroft dos_sectors = sectors = disklabel.d_nsectors;
953 1.31 jonathan dos_cylindersectors = cylindersectors = heads * sectors;
954 1.1 cgd disksectors = disklabel.d_secperunit;
955 1.4 mycroft
956 1.1 cgd return (0);
957 1.1 cgd }
958 1.4 mycroft
959 1.1 cgd int
960 1.1 cgd read_s0()
961 1.4 mycroft {
962 1.4 mycroft
963 1.4 mycroft if (read_disk(0, mboot.bootinst) == -1) {
964 1.4 mycroft warn("can't read fdisk partition table");
965 1.1 cgd return (-1);
966 1.32 thorpej }
967 1.12 thorpej if (getshort(&mboot.signature) != MBR_MAGIC) {
968 1.4 mycroft warnx("invalid fdisk partition table found");
969 1.1 cgd return (-1);
970 1.4 mycroft }
971 1.1 cgd return (0);
972 1.1 cgd }
973 1.4 mycroft
974 1.1 cgd int
975 1.1 cgd write_s0()
976 1.30 ws {
977 1.4 mycroft int flag, i;
978 1.1 cgd
979 1.1 cgd /*
980 1.1 cgd * write enable label sector before write (if necessary),
981 1.1 cgd * disable after writing.
982 1.1 cgd * needed if the disklabel protected area also protects
983 1.1 cgd * sector 0. (e.g. empty disk)
984 1.1 cgd */
985 1.1 cgd flag = 1;
986 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
987 1.4 mycroft warn("DIOCWLABEL");
988 1.4 mycroft if (write_disk(0, mboot.bootinst) == -1) {
989 1.1 cgd warn("can't write fdisk partition table");
990 1.4 mycroft return -1;
991 1.30 ws }
992 1.30 ws for (i = bootsize; (i -= 0x200) > 0;)
993 1.30 ws if (write_disk(i / 0x200, bootcode + i) == -1) {
994 1.30 ws warn("can't write bootcode");
995 1.30 ws return -1;
996 1.1 cgd }
997 1.4 mycroft flag = 0;
998 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
999 1.16 phil warn("DIOCWLABEL");
1000 1.1 cgd return 0;
1001 1.1 cgd }
1002 1.4 mycroft
1003 1.4 mycroft int
1004 1.4 mycroft yesno(str)
1005 1.4 mycroft char *str;
1006 1.4 mycroft {
1007 1.1 cgd int ch, first;
1008 1.1 cgd
1009 1.1 cgd printf("%s [n] ", str);
1010 1.4 mycroft
1011 1.4 mycroft first = ch = getchar();
1012 1.4 mycroft while (ch != '\n' && ch != EOF)
1013 1.4 mycroft ch = getchar();
1014 1.1 cgd return (first == 'y' || first == 'Y');
1015 1.1 cgd }
1016 1.5 mycroft
1017 1.5 mycroft void
1018 1.4 mycroft decimal(str, num)
1019 1.5 mycroft char *str;
1020 1.1 cgd int *num;
1021 1.8 cgd {
1022 1.4 mycroft int acc = 0;
1023 1.1 cgd char *cp;
1024 1.5 mycroft
1025 1.5 mycroft for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
1026 1.1 cgd printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
1027 1.1 cgd
1028 1.7 mycroft fgets(lbuf, LBUF, stdin);
1029 1.7 mycroft lbuf[strlen(lbuf)-1] = '\0';
1030 1.7 mycroft cp = lbuf;
1031 1.7 mycroft
1032 1.7 mycroft cp += strspn(cp, " \t");
1033 1.5 mycroft if (*cp == '\0')
1034 1.1 cgd return;
1035 1.7 mycroft
1036 1.7 mycroft if (!isdigit(*cp))
1037 1.5 mycroft continue;
1038 1.7 mycroft acc = strtol(lbuf, &cp, 10);
1039 1.5 mycroft
1040 1.5 mycroft cp += strspn(cp, " \t");
1041 1.5 mycroft if (*cp != '\0')
1042 1.1 cgd continue;
1043 1.5 mycroft
1044 1.5 mycroft *num = acc;
1045 1.1 cgd return;
1046 1.1 cgd }
1047 1.1 cgd
1048 1.1 cgd }
1049 1.4 mycroft
1050 1.4 mycroft int
1051 1.4 mycroft type_match(key, item)
1052 1.4 mycroft const void *key, *item;
1053 1.4 mycroft {
1054 1.4 mycroft const int *typep = key;
1055 1.4 mycroft const struct part_type *ptr = item;
1056 1.4 mycroft
1057 1.4 mycroft if (*typep < ptr->type)
1058 1.4 mycroft return (-1);
1059 1.4 mycroft if (*typep > ptr->type)
1060 1.4 mycroft return (1);
1061 1.4 mycroft return (0);
1062 1.4 mycroft }
1063 1.4 mycroft
1064 1.4 mycroft char *
1065 1.4 mycroft get_type(type)
1066 1.4 mycroft int type;
1067 1.4 mycroft {
1068 1.4 mycroft struct part_type *ptr;
1069 1.4 mycroft
1070 1.4 mycroft ptr = bsearch(&type, part_types,
1071 1.4 mycroft sizeof(part_types) / sizeof(struct part_type),
1072 1.4 mycroft sizeof(struct part_type), type_match);
1073 1.4 mycroft if (ptr == 0)
1074 1.16 phil return ("unknown");
1075 1.1 cgd return (ptr->name);
1076 }
1077