2 * Mach Operating System
3 * Copyright (c) 1992 Carnegie Mellon University
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
16 * Carnegie Mellon requests users of this software to return to
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
27 #include <sys/types.h>
28 #include <sys/disklabel.h>
31 #include <sys/ioctl.h>
37 static char lbuf[LBUF];
41 * Ported to 386bsd by Julian Elischer Thu Oct 15 20:26:46 PDT 1992
43 * 14-Dec-89 Robert Baron (rvb) at Carnegie-Mellon University
44 * Copyright (c) 1989 Robert. V. Baron
48 #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
49 #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
50 #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
52 #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
56 char *disk = "/dev/rwd0d";
59 struct disklabel disklabel; /* disk parameters */
61 int cyls, sectors, heads, cylsecs, disksecs;
65 unsigned char padding[2]; /* force the longs to be long alligned */
66 unsigned char bootinst[DOSPARTOFF];
67 struct dos_partition parts[4];
68 unsigned short int signature;
73 #define BOOT_MAGIC 0xAA55
80 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
81 #define DOSCYL(c) (c & 0xff)
84 static int partition = -1;
87 static int a_flag = 0; /* set active partition */
88 static int i_flag = 0; /* replace partition data */
89 static int u_flag = 0; /* update partition data */
91 static unsigned char bootcode[] = {
92 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
93 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
94 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
95 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
96 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
97 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
98 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
99 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
100 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
101 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
102 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
103 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
104 'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
105 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
106 'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
107 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
108 'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
110 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
118 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
120 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
122 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
132 ,{0x01, "Primary DOS with 12 bit FAT"}
133 ,{0x02, "XENIX / filesystem"}
134 ,{0x03, "XENIX /usr filesystem"}
135 ,{0x04, "Primary DOS with 16 bit FAT"}
136 ,{0x05, "Extended DOS"}
137 ,{0x06, "Primary 'big' DOS (> 32MB)"}
138 ,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
139 ,{0x08, "AIX filesystem"}
140 ,{0x09, "AIX boot partition or Coherent"}
141 ,{0x0A, "OS/2 Boot Manager or OPUS"}
146 ,{0x52, "CP/M or Microport SysV/AT"}
149 ,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
150 ,{0x64, "Novell Netware 2.xx"}
151 ,{0x65, "Novell Netware 3.xx"}
153 ,{0x80, "Minix 1.1 ... 1.4a"}
154 ,{0x81, "Minix 1.4b ... 1.5.10"}
156 ,{0x93, "Amoeba filesystem"}
157 ,{0x94, "Amoeba bad block table"}
159 ,{0xB7, "BSDI BSD/386 filesystem"}
160 ,{0xB8, "BSDI BSD/386 swap"}
161 ,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
166 ,{0xF2, "DOS 3.3+ Secondary"}
168 ,{0xFF, "BBT (Bad Blocks Table)"}
178 {register char *cp = name;
179 while (*cp) if (*cp++ == '/') name = cp;
182 for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
183 if (*token++ != '-' || !*token)
185 else { register int flag;
186 for ( ; flag = *token++ ; ) {
218 if (open_disk(u_flag) < 0)
221 printf("******* Working on device %s *******\n",disk);
234 printf("Warning: BIOS sector numbering starts with sector 1\n");
235 printf("Information from DOS bootblock is:\n");
237 for (i = 0; i < NDOSPART; i++)
240 change_part(partition);
242 if (u_flag || a_flag)
243 change_active(partition);
245 if (u_flag || a_flag) {
246 printf("\nWe haven't changed the partition table yet. ");
247 printf("This is your last chance.\n");
249 if (ok("Should we write new partition table?"))
256 printf("fdisk {-a|-i|-r} {disk}\n");
264 printf("Information from DOS bootblock is:\n");
266 for (i = 0; i < NDOSPART; i++)
267 printf("%d: ", i), print_part(i);
272 static struct dos_partition mtpart = { 0 };
276 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
279 if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
280 printf("<UNUSED>\n");
283 printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
284 printf(" start %d, size %d (%d Meg), flag %x\n",
286 partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
288 printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
289 ,DPCYL(partp->dp_scyl, partp->dp_ssect)
290 ,DPSECT(partp->dp_ssect)
292 ,DPCYL(partp->dp_ecyl, partp->dp_esect)
293 ,DPSECT(partp->dp_esect)
299 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
300 int size = disksecs - start;
303 memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
304 mboot.signature = BOOT_MAGIC;
306 partp->dp_typ = DOSPTYP_386BSD;
307 partp->dp_flag = ACTIVE;
308 partp->dp_start = start;
309 partp->dp_size = size;
311 dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
312 dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
317 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
319 printf("The data for partition %d is:\n", i);
322 if (u_flag && ok("Do you want to change it?")) {
326 bzero((char *)partp, sizeof (struct dos_partition));
329 printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
335 Decimal("sysid", partp->dp_typ, tmp);
336 Decimal("start", partp->dp_start, tmp);
337 Decimal("size", partp->dp_size, tmp);
339 if (ok("Explicitly specifiy beg/end address ?"))
342 tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
344 tsec = DPSECT(partp->dp_ssect);
345 Decimal("beginning cylinder", tcyl, tmp);
346 Decimal("beginning head", thd, tmp);
347 Decimal("beginning sector", tsec, tmp);
348 partp->dp_scyl = DOSCYL(tcyl);
349 partp->dp_ssect = DOSSECT(tsec,tcyl);
352 tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
354 tsec = DPSECT(partp->dp_esect);
355 Decimal("ending cylinder", tcyl, tmp);
356 Decimal("ending head", thd, tmp);
357 Decimal("ending sector", tsec, tmp);
358 partp->dp_ecyl = DOSCYL(tcyl);
359 partp->dp_esect = DOSSECT(tsec,tcyl);
363 &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
364 dos(partp->dp_start+partp->dp_size - 1,
365 &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
369 } while (!ok("Are we happy with this entry?"));
375 printf("parameters extracted from in-core disklabel are:\n");
376 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
377 ,cyls,heads,sectors,cylsecs);
378 if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
379 printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
380 printf("parameters to be used for BIOS calculations are:\n");
381 printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
382 ,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
389 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
391 if (a_flag && which != -1)
393 if (ok("Do you want to change the active partition?")) {
395 Decimal("active partition", active, tmp);
396 while(!ok("Are you happy with this choice"));
398 for (i = 0; i < NDOSPART; i++)
399 partp[i].dp_flag = 0;
400 partp[active].dp_flag = ACTIVE;
407 if (ok("Do you want to change our idea of what BIOS thinks ?"))
411 Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
412 Decimal("BIOS's idea of #heads", dos_heads, tmp);
413 Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
414 dos_cylsecs = dos_heads * dos_sectors;
417 while(!ok("Are you happy with this choice"));
421 /***********************************************\
422 * Change real numbers into strange dos numbers *
423 \***********************************************/
427 unsigned char *c, *s, *h;
432 cy = sec / ( dos_cylsecs );
433 sec = sec - cy * ( dos_cylsecs );
435 hd = sec / dos_sectors;
436 sec = (sec - hd * dos_sectors) + 1;
440 *s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
445 /* Getting device status */
451 if (stat(disk, &st) == -1) {
452 fprintf(stderr, "%s: Can't get file status of %s\n",
455 } else if ( !(st.st_mode & S_IFCHR) ) {
456 fprintf(stderr,"%s: Device %s is not character special\n",
460 if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) {
461 fprintf(stderr,"%s: Can't open device %s\n", name, disk);
464 if (get_params(0) == -1) {
465 fprintf(stderr, "%s: Can't get disk parameters on %s\n",
473 read_disk(sector, buf)
475 lseek(fd,(sector * 512), 0);
476 return read(fd, buf, 512);
479 write_disk(sector, buf)
481 lseek(fd,(sector * 512), 0);
482 return write(fd, buf, 512);
488 if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
492 dos_cyls = cyls = disklabel.d_ncylinders;
493 dos_heads = heads = disklabel.d_ntracks;
494 dos_sectors = sectors = disklabel.d_nsectors;
495 dos_cylsecs = cylsecs = heads * sectors;
496 disksecs = cyls * heads * sectors;
504 if (read_disk(0, (char *) mboot.bootinst) == -1) {
505 fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
508 if (mboot.signature != BOOT_MAGIC) {
509 fprintf(stderr, "%s: Invalid fdisk partition table found\n",
511 /* So should we initialize things */
525 * write enable label sector before write (if necessary),
526 * disable after writing.
527 * needed if the disklabel protected area also protects
528 * sector 0. (e.g. empty disk)
531 if (ioctl(fd, DIOCWLABEL, &flag) < 0)
532 perror("ioctl DIOCWLABEL");
533 if (write_disk(0, (char *) mboot.bootinst) == -1) {
534 fprintf(stderr, "%s: Can't write fdisk partition table\n",
538 (void) ioctl(fd, DIOCWLABEL, &flag);
547 printf("%s [n] ", str);
548 fgets(lbuf, LBUF, stdin);
549 lbuf[strlen(lbuf)-1] = 0;
552 (!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
553 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
559 decimal(str, num, deflt)
567 printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
568 fgets(lbuf, LBUF, stdin);
569 lbuf[strlen(lbuf)-1] = 0;
575 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
579 if (c <= '9' && c >= '0')
580 acc = acc * 10 + c - '0';
584 if (c == ' ' || c == '\t')
585 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
590 printf("%s is an invalid decimal number. Try again\n",
604 printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
605 fgets(lbuf, LBUF, stdin);
606 lbuf[strlen(lbuf)-1] = 0;
612 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
616 if (c <= '9' && c >= '0')
617 acc = (acc << 4) + c - '0';
618 else if (c <= 'f' && c >= 'a')
619 acc = (acc << 4) + c - 'a' + 10;
620 else if (c <= 'F' && c >= 'A')
621 acc = (acc << 4) + c - 'A' + 10;
625 if (c == ' ' || c == '\t')
626 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
631 printf("%s is an invalid hex number. Try again\n",
645 printf("Supply a string value for \"%s\" [%s] ", str, *ans);
646 fgets(lbuf, LBUF, stdin);
647 lbuf[strlen(lbuf)-1] = 0;
652 while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
656 while ((c = *cp) && c != '"') cp++;
659 while ((c = *cp) && c != ' ' && c != '\t') cp++;
671 int numentries = (sizeof(part_types)/sizeof(struct part_type));
673 struct part_type *ptr = part_types;
676 while(counter < numentries)
678 if(ptr->type == type)