fdisk.c revision 1.5 1 1.4 mycroft /*
2 1.1 cgd * Mach Operating System
3 1.1 cgd * Copyright (c) 1992 Carnegie Mellon University
4 1.1 cgd * All Rights Reserved.
5 1.4 mycroft *
6 1.1 cgd * Permission to use, copy, modify and distribute this software and its
7 1.1 cgd * documentation is hereby granted, provided that both the copyright
8 1.1 cgd * notice and this permission notice appear in all copies of the
9 1.1 cgd * software, derivative works or modified versions, and any portions
10 1.1 cgd * thereof, and that both notices appear in supporting documentation.
11 1.4 mycroft *
12 1.1 cgd * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 1.1 cgd * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 1.1 cgd * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 1.4 mycroft *
16 1.1 cgd * Carnegie Mellon requests users of this software to return to
17 1.4 mycroft *
18 1.1 cgd * Software Distribution Coordinator or Software.Distribution (at) CS.CMU.EDU
19 1.1 cgd * School of Computer Science
20 1.1 cgd * Carnegie Mellon University
21 1.1 cgd * Pittsburgh PA 15213-3890
22 1.4 mycroft *
23 1.1 cgd * any improvements or extensions that they make and grant Carnegie Mellon
24 1.1 cgd * the rights to redistribute these changes.
25 1.1 cgd */
26 1.1 cgd
27 1.2 mycroft #ifndef lint
28 1.5 mycroft static char rcsid[] = "$Id: fdisk.c,v 1.5 1994/09/23 05:30:10 mycroft Exp $";
29 1.2 mycroft #endif /* not lint */
30 1.2 mycroft
31 1.1 cgd #include <sys/types.h>
32 1.1 cgd #include <sys/disklabel.h>
33 1.4 mycroft #include <sys/ioctl.h>
34 1.1 cgd #include <sys/stat.h>
35 1.4 mycroft
36 1.4 mycroft #include <err.h>
37 1.1 cgd #include <fcntl.h>
38 1.4 mycroft #include <stdio.h>
39 1.4 mycroft #include <stdlib.h>
40 1.1 cgd
41 1.1 cgd #define LBUF 100
42 1.1 cgd static char lbuf[LBUF];
43 1.1 cgd
44 1.1 cgd /*
45 1.1 cgd * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
46 1.1 cgd * Copyright (c) 1989 Robert. V. Baron
47 1.1 cgd * Created.
48 1.1 cgd */
49 1.1 cgd
50 1.1 cgd char *disk = "/dev/rwd0d";
51 1.1 cgd
52 1.1 cgd struct disklabel disklabel; /* disk parameters */
53 1.1 cgd
54 1.5 mycroft int cylinders, sectors, heads, cylindersectors, disksectors;
55 1.1 cgd
56 1.4 mycroft struct mboot {
57 1.1 cgd unsigned char padding[2]; /* force the longs to be long alligned */
58 1.1 cgd unsigned char bootinst[DOSPARTOFF];
59 1.1 cgd struct dos_partition parts[4];
60 1.1 cgd unsigned short int signature;
61 1.1 cgd };
62 1.1 cgd struct mboot mboot;
63 1.1 cgd
64 1.1 cgd #define ACTIVE 0x80
65 1.1 cgd #define BOOT_MAGIC 0xAA55
66 1.1 cgd
67 1.5 mycroft int dos_cylinders;
68 1.1 cgd int dos_heads;
69 1.1 cgd int dos_sectors;
70 1.5 mycroft int dos_cylindersectors;
71 1.1 cgd
72 1.4 mycroft #define DOSSECT(s,c) (((s) & 0x3f) | (((c) >> 2) & 0xc0))
73 1.4 mycroft #define DOSCYL(c) ((c) & 0xff)
74 1.4 mycroft int partition = -1;
75 1.4 mycroft
76 1.4 mycroft int a_flag; /* set active partition */
77 1.4 mycroft int i_flag; /* replace partition data */
78 1.4 mycroft int u_flag; /* update partition data */
79 1.4 mycroft
80 1.4 mycroft unsigned char bootcode[] = {
81 1.4 mycroft 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
82 1.4 mycroft 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
83 1.4 mycroft 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
84 1.4 mycroft 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
85 1.4 mycroft 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
86 1.4 mycroft 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
87 1.4 mycroft 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
88 1.4 mycroft 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
89 1.1 cgd 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
90 1.1 cgd 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
91 1.1 cgd 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
92 1.4 mycroft 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
93 1.1 cgd 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
94 1.1 cgd 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
95 1.1 cgd 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
96 1.1 cgd 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
97 1.4 mycroft 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
98 1.1 cgd
99 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
101 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
102 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
103 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
104 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
106 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 1.4 mycroft 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
112 1.1 cgd };
113 1.1 cgd
114 1.4 mycroft struct part_type {
116 1.4 mycroft int type;
117 1.4 mycroft char *name;
118 1.4 mycroft } part_types[] = {
119 1.4 mycroft {0x00, "unused"},
120 1.4 mycroft {0x01, "Primary DOS with 12 bit FAT"},
121 1.4 mycroft {0x02, "XENIX / filesystem"},
122 1.4 mycroft {0x03, "XENIX /usr filesystem"},
123 1.4 mycroft {0x04, "Primary DOS with 16 bit FAT"},
124 1.4 mycroft {0x05, "Extended DOS"},
125 1.4 mycroft {0x06, "Primary 'big' DOS (> 32MB)"},
126 1.4 mycroft {0x07, "OS/2 HPFS, QNX or Advanced UNIX"},
127 1.4 mycroft {0x08, "AIX filesystem"},
128 1.4 mycroft {0x09, "AIX boot partition or Coherent"},
129 1.4 mycroft {0x0A, "OS/2 Boot Manager or OPUS"},
130 1.4 mycroft {0x10, "OPUS"},
131 1.4 mycroft {0x40, "VENIX 286"},
132 1.4 mycroft {0x50, "DM"},
133 1.4 mycroft {0x51, "DM"},
134 1.4 mycroft {0x52, "CP/M or Microport SysV/AT"},
135 1.4 mycroft {0x56, "GB"},
136 1.4 mycroft {0x61, "Speed"},
137 1.4 mycroft {0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"},
138 1.4 mycroft {0x64, "Novell Netware 2.xx"},
139 1.4 mycroft {0x65, "Novell Netware 3.xx"},
140 1.4 mycroft {0x75, "PCIX"},
141 1.4 mycroft {0x80, "Minix 1.1 ... 1.4a"},
142 1.4 mycroft {0x81, "Minix 1.4b ... 1.5.10"},
143 1.4 mycroft {0x82, "Linux"},
144 1.4 mycroft {0x93, "Amoeba filesystem"},
145 1.4 mycroft {0x94, "Amoeba bad block table"},
146 1.4 mycroft {0xA5, "NetBSD"},
147 1.4 mycroft {0xB7, "BSDI BSD/386 filesystem"},
148 1.4 mycroft {0xB8, "BSDI BSD/386 swap"},
149 1.4 mycroft {0xDB, "Concurrent CPM or C.DOS or CTOS"},
150 1.4 mycroft {0xE1, "Speed"},
151 1.4 mycroft {0xE3, "Speed"},
152 1.4 mycroft {0xE4, "Speed"},
153 1.4 mycroft {0xF1, "Speed"},
154 1.4 mycroft {0xF2, "DOS 3.3+ Secondary"},
155 1.4 mycroft {0xF4, "Speed"},
156 1.1 cgd {0xFF, "BBT (Bad Blocks Table)"},
157 1.1 cgd };
158 1.4 mycroft
159 1.4 mycroft void usage __P((void));
160 1.4 mycroft void print_s0 __P((int));
161 1.4 mycroft void print_part __P((int));
162 1.4 mycroft void init_sector0 __P((int));
163 1.4 mycroft void change_part __P((int));
164 1.4 mycroft void print_params __P((void));
165 1.4 mycroft void change_active __P((int));
166 1.4 mycroft void get_params_to_use __P((void));
167 1.4 mycroft void dos __P((int, unsigned char *, unsigned char *, unsigned char *));
168 1.4 mycroft int open_disk __P((int));
169 1.4 mycroft int read_disk __P((int, void *));
170 1.4 mycroft int write_disk __P((int, void *));
171 1.4 mycroft int get_params __P((void));
172 1.4 mycroft int read_s0 __P((void));
173 1.4 mycroft int write_s0 __P((void));
174 1.5 mycroft int yesno __P((char *));
175 1.4 mycroft void decimal __P((char *, int *));
176 1.4 mycroft int type_match __P((const void *, const void *));
177 1.1 cgd char *get_type __P((int));
178 1.4 mycroft
179 1.1 cgd int
180 1.4 mycroft main(argc, argv)
181 1.4 mycroft int argc;
182 1.1 cgd char *argv[];
183 1.4 mycroft {
184 1.4 mycroft int ch;
185 1.1 cgd int part;
186 1.4 mycroft
187 1.4 mycroft a_flag = i_flag = u_flag = 0;
188 1.4 mycroft while ((ch = getopt(argc, argv, "0123aiu")) != -1)
189 1.4 mycroft switch (ch) {
190 1.4 mycroft case '0':
191 1.4 mycroft partition = 0;
192 1.4 mycroft break;
193 1.4 mycroft case '1':
194 1.4 mycroft partition = 1;
195 1.4 mycroft break;
196 1.4 mycroft case '2':
197 1.4 mycroft partition = 2;
198 1.4 mycroft break;
199 1.4 mycroft case '3':
200 1.4 mycroft partition = 3;
201 1.4 mycroft break;
202 1.4 mycroft case 'a':
203 1.4 mycroft a_flag = 1;
204 1.4 mycroft break;
205 1.4 mycroft case 'i':
206 1.4 mycroft i_flag = 1;
207 1.4 mycroft case 'u':
208 1.1 cgd u_flag = 1;
209 1.4 mycroft break;
210 1.4 mycroft default:
211 1.1 cgd usage();
212 1.4 mycroft }
213 1.4 mycroft argc -= optind;
214 1.1 cgd argv += optind;
215 1.1 cgd
216 1.1 cgd if (argc > 0)
217 1.4 mycroft disk = argv[0];
218 1.4 mycroft
219 1.1 cgd if (open_disk(a_flag || i_flag || u_flag) < 0)
220 1.1 cgd exit(1);
221 1.4 mycroft
222 1.4 mycroft printf("******* Working on device %s *******\n", disk);
223 1.1 cgd if (u_flag)
224 1.1 cgd get_params_to_use();
225 1.1 cgd else
226 1.1 cgd print_params();
227 1.1 cgd
228 1.1 cgd if (read_s0())
229 1.1 cgd init_sector0(1);
230 1.1 cgd
231 1.1 cgd printf("Warning: BIOS sector numbering starts with sector 1\n");
232 1.4 mycroft printf("Information from DOS bootblock is:\n");
233 1.4 mycroft if (partition == -1) {
234 1.4 mycroft for (part = 0; part < NDOSPART; part++)
235 1.4 mycroft change_part(part);
236 1.1 cgd } else
237 1.1 cgd change_part(partition);
238 1.1 cgd
239 1.1 cgd if (u_flag || a_flag)
240 1.1 cgd change_active(partition);
241 1.1 cgd
242 1.1 cgd if (u_flag || a_flag) {
243 1.1 cgd printf("\nWe haven't changed the partition table yet. ");
244 1.1 cgd printf("This is your last chance.\n");
245 1.4 mycroft print_s0(-1);
246 1.1 cgd if (yesno("Should we write new partition table?"))
247 1.1 cgd write_s0();
248 1.1 cgd }
249 1.1 cgd
250 1.4 mycroft exit(0);
251 1.1 cgd }
252 1.4 mycroft
253 1.4 mycroft void
254 1.4 mycroft usage()
255 1.4 mycroft {
256 1.4 mycroft
257 1.4 mycroft (void)fprintf(stderr, "usage: fdisk [-aiu] [-0|-1|-2|-3] [device]\n");
258 1.1 cgd exit(1);
259 1.1 cgd }
260 1.4 mycroft
261 1.1 cgd void
262 1.4 mycroft print_s0(which)
263 1.1 cgd int which;
264 1.4 mycroft {
265 1.1 cgd int part;
266 1.1 cgd
267 1.1 cgd print_params();
268 1.4 mycroft printf("Information from DOS bootblock is:\n");
269 1.4 mycroft if (which == -1) {
270 1.4 mycroft for (part = 0; part < NDOSPART; part++)
271 1.4 mycroft printf("%d: ", part), print_part(part);
272 1.1 cgd } else
273 1.1 cgd print_part(which);
274 1.1 cgd }
275 1.1 cgd
276 1.1 cgd static struct dos_partition mtpart = { 0 };
277 1.4 mycroft
278 1.4 mycroft void
279 1.4 mycroft print_part(part)
280 1.1 cgd int part;
281 1.4 mycroft {
282 1.1 cgd struct dos_partition *partp;
283 1.4 mycroft
284 1.4 mycroft partp = &mboot.parts[part];
285 1.1 cgd if (!bcmp(partp, &mtpart, sizeof(struct dos_partition))) {
286 1.1 cgd printf("<UNUSED>\n");
287 1.1 cgd return;
288 1.5 mycroft }
289 1.4 mycroft printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
290 1.4 mycroft printf(" start %d, size %d (%d MB), flag %x\n",
291 1.4 mycroft partp->dp_start, partp->dp_size,
292 1.5 mycroft partp->dp_size * 512 / (1024 * 1024), partp->dp_flag);
293 1.5 mycroft printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
294 1.5 mycroft DPCYL(partp->dp_scyl, partp->dp_ssect),
295 1.5 mycroft partp->dp_shd, DPSECT(partp->dp_ssect));
296 1.5 mycroft printf("\tend: cylinder %4d, head %3d, sector %2d\n",
297 1.5 mycroft DPCYL(partp->dp_ecyl, partp->dp_esect),
298 1.1 cgd partp->dp_ehd, DPSECT(partp->dp_esect));
299 1.1 cgd }
300 1.4 mycroft
301 1.1 cgd void
302 1.4 mycroft init_sector0(start)
303 1.1 cgd int start;
304 1.4 mycroft {
305 1.1 cgd struct dos_partition *partp;
306 1.4 mycroft
307 1.1 cgd memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
308 1.1 cgd mboot.signature = BOOT_MAGIC;
309 1.4 mycroft
310 1.1 cgd partp = &mboot.parts[3];
311 1.1 cgd partp->dp_typ = DOSPTYP_386BSD;
312 1.1 cgd partp->dp_flag = ACTIVE;
313 1.5 mycroft partp->dp_start = start;
314 1.1 cgd partp->dp_size = disksectors - start;
315 1.4 mycroft
316 1.4 mycroft dos(partp->dp_start,
317 1.4 mycroft &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
318 1.4 mycroft dos(partp->dp_start + partp->dp_size - 1,
319 1.1 cgd &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
320 1.1 cgd }
321 1.4 mycroft
322 1.4 mycroft void
323 1.4 mycroft change_part(part)
324 1.1 cgd int part;
325 1.4 mycroft {
326 1.1 cgd struct dos_partition *partp;
327 1.4 mycroft
328 1.1 cgd partp = &mboot.parts[part];
329 1.4 mycroft
330 1.4 mycroft printf("The data for partition %d is:\n", part);
331 1.4 mycroft print_part(part);
332 1.4 mycroft
333 1.4 mycroft if (!u_flag || !yesno("Do you want to change it?"))
334 1.1 cgd return;
335 1.1 cgd
336 1.4 mycroft if (i_flag) {
337 1.4 mycroft memset(partp, '\0', sizeof(*partp));
338 1.1 cgd if (part == 3) {
339 1.1 cgd init_sector0(1);
340 1.4 mycroft printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
341 1.1 cgd print_part(part);
342 1.1 cgd }
343 1.1 cgd }
344 1.1 cgd
345 1.5 mycroft do {
346 1.5 mycroft {
347 1.5 mycroft int sysid, start, size;
348 1.5 mycroft
349 1.5 mycroft sysid = partp->dp_typ,
350 1.5 mycroft start = partp->dp_start,
351 1.5 mycroft size = partp->dp_size;
352 1.5 mycroft decimal("sysid", &sysid);
353 1.5 mycroft decimal("start", &start);
354 1.5 mycroft decimal("size", &size);
355 1.5 mycroft partp->dp_typ = sysid;
356 1.5 mycroft partp->dp_start = start;
357 1.5 mycroft partp->dp_size = size;
358 1.1 cgd }
359 1.4 mycroft
360 1.5 mycroft if (yesno("Explicitly specifiy beg/end address ?")) {
361 1.4 mycroft int tsector, tcylinder, thead;
362 1.5 mycroft
363 1.5 mycroft tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect);
364 1.5 mycroft thead = partp->dp_shd;
365 1.5 mycroft tsector = DPSECT(partp->dp_ssect);
366 1.5 mycroft decimal("beginning cylinder", &tcylinder);
367 1.5 mycroft decimal("beginning head", &thead);
368 1.5 mycroft decimal("beginning sector", &tsector);
369 1.5 mycroft partp->dp_scyl = DOSCYL(tcylinder);
370 1.5 mycroft partp->dp_shd = thead;
371 1.5 mycroft partp->dp_ssect = DOSSECT(tsector, tcylinder);
372 1.5 mycroft
373 1.5 mycroft tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect);
374 1.5 mycroft thead = partp->dp_ehd;
375 1.5 mycroft tsector = DPSECT(partp->dp_esect);
376 1.5 mycroft decimal("ending cylinder", &tcylinder);
377 1.5 mycroft decimal("ending head", &thead);
378 1.5 mycroft decimal("ending sector", &tsector);
379 1.5 mycroft partp->dp_ecyl = DOSCYL(tcylinder);
380 1.5 mycroft partp->dp_ehd = thead;
381 1.1 cgd partp->dp_esect = DOSSECT(tsector, tcylinder);
382 1.1 cgd } else {
383 1.4 mycroft dos(partp->dp_start,
384 1.4 mycroft &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
385 1.4 mycroft dos(partp->dp_start + partp->dp_size - 1,
386 1.1 cgd &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
387 1.4 mycroft }
388 1.4 mycroft
389 1.4 mycroft print_part(part);
390 1.1 cgd } while (!yesno("Are we happy with this entry?"));
391 1.1 cgd }
392 1.4 mycroft
393 1.1 cgd void
394 1.1 cgd print_params()
395 1.4 mycroft {
396 1.1 cgd
397 1.5 mycroft printf("parameters extracted from in-core disklabel are:\n");
398 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
399 1.5 mycroft cylinders, heads, sectors, cylindersectors);
400 1.5 mycroft if (dos_sectors > 63 || dos_cylinders > 1023 || dos_heads > 255)
401 1.1 cgd printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
402 1.5 mycroft printf("parameters to be used for BIOS calculations are:\n");
403 1.5 mycroft printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
404 1.1 cgd dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
405 1.1 cgd }
406 1.4 mycroft
407 1.1 cgd void
408 1.4 mycroft change_active(which)
409 1.1 cgd int which;
410 1.4 mycroft {
411 1.4 mycroft struct dos_partition *partp;
412 1.5 mycroft int part;
413 1.4 mycroft int active = 3;
414 1.4 mycroft
415 1.1 cgd partp = &mboot.parts[0];
416 1.1 cgd
417 1.1 cgd if (a_flag && which != -1)
418 1.4 mycroft active = which;
419 1.4 mycroft else {
420 1.4 mycroft for (part = 0; part < NDOSPART; part++)
421 1.4 mycroft if (partp[part].dp_flag & ACTIVE)
422 1.4 mycroft active = part;
423 1.4 mycroft }
424 1.4 mycroft if (yesno("Do you want to change the active partition?")) {
425 1.5 mycroft do {
426 1.4 mycroft decimal("active partition", &active);
427 1.1 cgd } while (!yesno("Are you happy with this choice?"));
428 1.4 mycroft }
429 1.4 mycroft for (part = 0; part < NDOSPART; part++)
430 1.4 mycroft partp[part].dp_flag &= ~ACTIVE;
431 1.1 cgd partp[active].dp_flag |= ACTIVE;
432 1.1 cgd }
433 1.4 mycroft
434 1.1 cgd void
435 1.1 cgd get_params_to_use()
436 1.4 mycroft {
437 1.1 cgd
438 1.4 mycroft print_params();
439 1.4 mycroft if (yesno("Do you want to change our idea of what BIOS thinks?")) {
440 1.5 mycroft do {
441 1.5 mycroft decimal("BIOS's idea of #cylinders", &dos_cylinders);
442 1.5 mycroft decimal("BIOS's idea of #heads", &dos_heads);
443 1.5 mycroft decimal("BIOS's idea of #sectors", &dos_sectors);
444 1.1 cgd dos_cylindersectors = dos_heads * dos_sectors;
445 1.4 mycroft print_params();
446 1.1 cgd } while (!yesno("Are you happy with this choice?"));
447 1.1 cgd }
448 1.1 cgd }
449 1.1 cgd
450 1.1 cgd /***********************************************\
451 1.1 cgd * Change real numbers into strange dos numbers *
452 1.4 mycroft \***********************************************/
453 1.5 mycroft void
454 1.5 mycroft dos(sector, cylinderp, headp, sectorp)
455 1.5 mycroft int sector;
456 1.4 mycroft unsigned char *cylinderp, *headp, *sectorp;
457 1.5 mycroft {
458 1.4 mycroft int cylinder, head;
459 1.5 mycroft
460 1.5 mycroft cylinder = sector / dos_cylindersectors;
461 1.4 mycroft sector -= cylinder * dos_cylindersectors;
462 1.5 mycroft
463 1.5 mycroft head = sector / dos_sectors;
464 1.4 mycroft sector -= head * dos_sectors;
465 1.5 mycroft
466 1.5 mycroft *cylinderp = DOSCYL(cylinder);
467 1.5 mycroft *headp = head;
468 1.1 cgd *sectorp = DOSSECT(sector + 1, cylinder);
469 1.1 cgd }
470 1.1 cgd
471 1.1 cgd int fd;
472 1.4 mycroft
473 1.1 cgd int
474 1.4 mycroft open_disk(u_flag)
475 1.1 cgd int u_flag;
476 1.4 mycroft {
477 1.1 cgd struct stat st;
478 1.4 mycroft
479 1.4 mycroft if ((fd = open(disk, u_flag ? O_RDWR : O_RDONLY)) == -1) {
480 1.4 mycroft warn("%s", disk);
481 1.4 mycroft return (-1);
482 1.4 mycroft }
483 1.4 mycroft if (fstat(fd, &st) == -1) {
484 1.4 mycroft close(fd);
485 1.4 mycroft warn("%s", disk);
486 1.1 cgd return (-1);
487 1.4 mycroft }
488 1.4 mycroft if (!S_ISCHR(st.st_mode)) {
489 1.4 mycroft close(fd);
490 1.4 mycroft warnx("%s is not a character device", disk);
491 1.1 cgd return (-1);
492 1.4 mycroft }
493 1.4 mycroft if (get_params() == -1) {
494 1.4 mycroft close(fd);
495 1.1 cgd return (-1);
496 1.4 mycroft }
497 1.1 cgd return (0);
498 1.1 cgd }
499 1.4 mycroft
500 1.1 cgd int
501 1.4 mycroft read_disk(sector, buf)
502 1.4 mycroft int sector;
503 1.1 cgd void *buf;
504 1.4 mycroft {
505 1.4 mycroft
506 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
507 1.4 mycroft return (-1);
508 1.1 cgd return (read(fd, buf, 512));
509 1.1 cgd }
510 1.4 mycroft
511 1.1 cgd int
512 1.4 mycroft write_disk(sector, buf)
513 1.4 mycroft int sector;
514 1.1 cgd void *buf;
515 1.4 mycroft {
516 1.4 mycroft
517 1.4 mycroft if (lseek(fd, (off_t)(sector * 512), 0) == -1)
518 1.4 mycroft return (-1);
519 1.1 cgd return (write(fd, buf, 512));
520 1.1 cgd }
521 1.4 mycroft
522 1.4 mycroft int
523 1.1 cgd get_params()
524 1.1 cgd {
525 1.4 mycroft
526 1.4 mycroft if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
527 1.4 mycroft warn("DIOCGDINFO");
528 1.4 mycroft return (-1);
529 1.1 cgd }
530 1.5 mycroft
531 1.4 mycroft dos_cylinders = cylinders = disklabel.d_ncylinders;
532 1.4 mycroft dos_heads = heads = disklabel.d_ntracks;
533 1.5 mycroft dos_sectors = sectors = disklabel.d_nsectors;
534 1.5 mycroft dos_cylindersectors = cylindersectors = heads * sectors;
535 1.1 cgd disksectors = cylinders * heads * sectors;
536 1.4 mycroft
537 1.1 cgd return (0);
538 1.1 cgd }
539 1.4 mycroft
540 1.1 cgd int
541 1.1 cgd read_s0()
542 1.4 mycroft {
543 1.4 mycroft
544 1.4 mycroft if (read_disk(0, mboot.bootinst) == -1) {
545 1.4 mycroft warn("can't read fdisk partition table");
546 1.1 cgd return (-1);
547 1.1 cgd }
548 1.4 mycroft if (mboot.signature != BOOT_MAGIC) {
549 1.4 mycroft warn("invalid fdisk partition table found");
550 1.4 mycroft /* So should we initialize things? */
551 1.1 cgd return (-1);
552 1.4 mycroft }
553 1.1 cgd return (0);
554 1.1 cgd }
555 1.4 mycroft
556 1.1 cgd int
557 1.1 cgd write_s0()
558 1.4 mycroft {
559 1.4 mycroft int flag;
560 1.1 cgd
561 1.1 cgd /*
562 1.1 cgd * write enable label sector before write (if necessary),
563 1.1 cgd * disable after writing.
564 1.1 cgd * needed if the disklabel protected area also protects
565 1.1 cgd * sector 0. (e.g. empty disk)
566 1.1 cgd */
567 1.1 cgd flag = 1;
568 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
569 1.4 mycroft warn("DIOCWLABEL");
570 1.4 mycroft if (write_disk(0, mboot.bootinst) == -1) {
571 1.1 cgd warn("can't write fdisk partition table");
572 1.4 mycroft return -1;
573 1.1 cgd }
574 1.4 mycroft flag = 0;
575 1.4 mycroft if (ioctl(fd, DIOCWLABEL, &flag) < 0)
576 1.1 cgd warn("DIOCWLABEL");
577 1.1 cgd }
578 1.4 mycroft
579 1.4 mycroft int
580 1.4 mycroft yesno(str)
581 1.4 mycroft char *str;
582 1.4 mycroft {
583 1.1 cgd int ch, first;
584 1.1 cgd
585 1.1 cgd printf("%s [n] ", str);
586 1.4 mycroft
587 1.4 mycroft first = ch = getchar();
588 1.4 mycroft while (ch != '\n' && ch != EOF)
589 1.4 mycroft ch = getchar();
590 1.1 cgd return (first == 'y' || first == 'Y');
591 1.1 cgd }
592 1.5 mycroft
593 1.5 mycroft void
594 1.4 mycroft decimal(str, num)
595 1.5 mycroft char *str;
596 1.1 cgd int *num;
597 1.4 mycroft {
598 1.4 mycroft int acc = 0, c;
599 1.1 cgd char *cp;
600 1.5 mycroft
601 1.5 mycroft for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
602 1.1 cgd printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
603 1.1 cgd
604 1.1 cgd fgets(lbuf, LBUF, stdin);
605 1.5 mycroft lbuf[strlen(lbuf)-1] = 0;
606 1.5 mycroft if (lbuf[0] == '\0')
607 1.1 cgd return;
608 1.5 mycroft
609 1.5 mycroft acc = strtol(lbuf, &cp, 10);
610 1.5 mycroft if (cp == lbuf)
611 1.5 mycroft continue;
612 1.5 mycroft cp += strspn(cp, " \t");
613 1.5 mycroft if (*cp != '\0')
614 1.1 cgd continue;
615 1.5 mycroft
616 1.5 mycroft *num = acc;
617 1.1 cgd return;
618 1.1 cgd }
619 1.1 cgd
620 1.1 cgd }
621 1.4 mycroft
622 1.4 mycroft int
623 1.4 mycroft type_match(key, item)
624 1.4 mycroft const void *key, *item;
625 1.4 mycroft {
626 1.4 mycroft const int *typep = key;
627 1.4 mycroft const struct part_type *ptr = item;
628 1.4 mycroft
629 1.4 mycroft if (*typep < ptr->type)
630 1.4 mycroft return (-1);
631 1.4 mycroft if (*typep > ptr->type)
632 1.4 mycroft return (1);
633 1.4 mycroft return (0);
634 1.4 mycroft }
635 1.4 mycroft
636 1.4 mycroft char *
637 1.4 mycroft get_type(type)
638 1.4 mycroft int type;
639 1.4 mycroft {
640 1.4 mycroft struct part_type *ptr;
641 1.4 mycroft
642 1.4 mycroft ptr = bsearch(&type, part_types,
643 1.4 mycroft sizeof(part_types) / sizeof(struct part_type),
644 1.4 mycroft sizeof(struct part_type), type_match);
645 1.4 mycroft if (ptr == 0)
646 1.4 mycroft return ("unknown");
647 1.4 mycroft else
648 1.1 cgd return (ptr->name);
649 }
650