summaryrefslogtreecommitdiff
path: root/Bootinst.c
diff options
context:
space:
mode:
Diffstat (limited to 'Bootinst.c')
-rw-r--r--Bootinst.c256
1 files changed, 256 insertions, 0 deletions
diff --git a/Bootinst.c b/Bootinst.c
new file mode 100644
index 0000000..f0e470a
--- /dev/null
+++ b/Bootinst.c
@@ -0,0 +1,256 @@
+/*
+ * Boot installator.
+ * Author: Serge Vakulenko, <vak@kiae.su>
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <dos.h>
+
+#define BOOTFILE "boot.bin"
+#define SAVEFILE "bootsav.bin"
+#define SAVE2FILE "boot2sav.bin"
+
+#define PartAddr 0x1be /* Offset to partition table */
+#define ValidationAddr 0x1fe /* Offset to validation bytes */
+#define MAGIC 0xaa55 /* Validation tag */
+
+#define DISK1 0
+#define DISK2 1
+#define READ 0
+#define WRITE 1
+
+typedef struct PartitionEntry {
+ unsigned char bootIndicator;
+ unsigned char beginHead;
+ unsigned char beginSector;
+ unsigned char beginCyl;
+ unsigned char systemId;
+ unsigned char endHead;
+ unsigned char endSector;
+ unsigned char endCyl;
+ unsigned short relSectorLow;
+ unsigned short relSectorHigh;
+ unsigned short numSectorsLow;
+ unsigned short numSectorsHigh;
+} PartitionEntry;
+
+unsigned char bootRecord [512];
+unsigned char bootProg [512];
+
+char head1 [] = "ÚÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÂÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄ¿\n";
+char head2 [] = "³ ³Partition³Can ³Boot³ Beginning ³ Ending ³ Relative³Number of³\n";
+char head3 [] = "³N³ Type ³Boot³Part³Head Cyl Sect³Head Cyl Sect³ Sectors ³ Sectors ³\n";
+char head4 [] = "ÃÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÅÄÄÄÄÅÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÅÄÄÄÄÂÄÄÄÄÄÂÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄ´\n";
+char mid1 [] = "³%d³%-9.9s³%-4.4s³%-4.4s³%3u ³%4u ³%3u ³%3u ³%4u ³%3u ³%8lu ³%8lu ³\n";
+char mid2 [] = "ÃÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÅÄÄÄÄÅÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÅÄÄÄÄÅÄÄÄÄÄÅÄÄÄÄÅÄÄÄÄÄÄÄÄÄÅÄÄÄÄÄÄÄÄÄ´\n";
+char foot [] = "ÀÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÁÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÙ\n";
+
+void printtable (disk)
+{
+ PartitionEntry *part = (PartitionEntry *) (bootRecord + PartAddr);
+ int i, cb;
+ long relSectors;
+ long numSectors;
+ char *typeString, block [512];
+
+ printf ("\n");
+ printf (head1);
+ printf (head2);
+ printf (head3);
+ printf (head4);
+
+ for (i=0; i<4; ++i) {
+ switch (part->systemId) {
+ default: typeString = " ?????"; cb = 1; break;
+ case 0: typeString = " empty"; cb = 0; break;
+ case 1: typeString = " dos-12"; cb = 1; break;
+ case 2: typeString = " xenix"; cb = 1; break;
+ case 3: typeString = "xenix usr"; cb = 0; break;
+ case 4: typeString = " dos-16"; cb = 1; break;
+ case 5: typeString = " extend"; cb = 0; break;
+ case 6: typeString = " bigdos"; cb = 1; break;
+ case 7: typeString = " hpfs"; cb = 1; break;
+ case 0x75: typeString = " pcix"; cb = 1; break;
+ case 0xdb: typeString = " cp/m"; cb = 1; break;
+ case 0xff: typeString = " bbt"; cb = 0; break;
+ case 0x08: typeString = " aix"; cb = 0; break;
+ case 0x09: typeString = " coherent"; cb = 1; break;
+ case 0x0A: typeString = " os/2"; cb = 1; break;
+ case 0x10: typeString = " opus"; cb = 1; break;
+ case 0x40: typeString = "venix 286"; cb = 1; break;
+ case 0x50:
+ case 0x51: typeString = " dm"; cb = 1; break;
+ case 0x52: typeString = "microport"; cb = 1; break;
+ case 0x56: typeString = " gb"; cb = 1; break;
+ case 0x61:
+ case 0xE1:
+ case 0xE3:
+ case 0xE4:
+ case 0xF1:
+ case 0xF4: typeString = " speed"; cb = 1; break;
+ case 0x63: typeString = " unix"; cb = 1; break;
+ case 0x64: typeString = "novell286"; cb = 1; break;
+ case 0x65: typeString = "novell386"; cb = 1; break;
+ case 0x80: typeString = "old minix"; cb = 1; break;
+ case 0x81: typeString = " minix"; cb = 1; break;
+ case 0x82: typeString = " linux"; cb = 1; break;
+ case 0x93: typeString = " amoeba"; cb = 1; break;
+ case 0x94: typeString = "amoebaBBT"; cb = 0; break;
+ case 0xA5: typeString = " 386bsd"; cb = 1; break;
+ case 0x9f:
+ case 0xB7: typeString = " bsdi"; cb = 1; break;
+ case 0xB8: typeString = "bsdi swap"; cb = 0; break;
+ case 0xF2: typeString = " dos sec"; cb = 1; break;
+ }
+ relSectors = part->relSectorLow |
+ (unsigned long) part->relSectorHigh<<16;
+ numSectors = part->numSectorsLow |
+ (unsigned long) part->numSectorsHigh<<16;
+
+ if (cb && (bootio (disk, READ, part->beginHead, part->beginCyl,
+ part->beginSector, block) != 0 ||
+ *(short *) &block [ValidationAddr] != (short) MAGIC))
+ cb = 0;
+
+ printf (mid1, i+1, typeString, cb ? " yes" : " no",
+ (part->bootIndicator & 0x80) ? " yes" : " no",
+ part->beginHead, part->beginCyl |
+ part->beginSector<<2 & 0x300,
+ part->beginSector & 077, part->endHead,
+ part->endCyl | part->endSector<<2 & 0x300,
+ part->endSector & 077, relSectors, numSectors);
+ if (i < 3)
+ printf (mid2);
+ ++part;
+ }
+ printf (foot);
+}
+
+int yes ()
+{
+ char reply [80];
+
+ printf (" (yes/no) ");
+ fgets (reply, sizeof (reply), stdin);
+ return (!stricmp (reply, "y\n") || !stricmp (reply, "yes\n"));
+}
+
+int install (disk, file, savefile)
+char *file, *savefile;
+{
+ int rc, fd;
+
+ rc = bootio (disk, READ, 0, 0, 1, bootRecord);
+ if (rc) {
+ fprintf (stderr, "Error %d reading boot record from disk %d\n",
+ rc, disk);
+ return (-1);
+ }
+ if (*(short *) &bootRecord [ValidationAddr] != (short) MAGIC) {
+ fprintf (stderr, "Bad master boot record on disk %d!\n",
+ disk);
+ return (-1);
+ }
+
+ printtable (disk);
+
+ fd = open (file, O_RDONLY|O_BINARY);
+ if (fd < 0) {
+ fprintf (stderr, "Cannot read file %s\n", file);
+ return (-1);
+ }
+ if (read (fd, bootProg, 512) != 512) {
+ fprintf (stderr, "Error reading %s\n", file);
+ return (-1);
+ }
+ close (fd);
+ if (*(short *) &bootProg [ValidationAddr] != (short) MAGIC) {
+ fprintf (stderr, "Bad boot image in file %s\n", file);
+ return (-1);
+ }
+
+ printf ("\nAre you sure you want to install new boot on disk %d?",
+ disk);
+ if (! yes ())
+ return (0);
+
+ close (creat (savefile, 0664));
+ fd = open (savefile, O_WRONLY|O_BINARY);
+ if (fd < 0) {
+ fprintf (stderr, "Cannot write to file %s\n", savefile);
+ return (-1);
+ }
+ if (write (fd, bootRecord, 512) != 512) {
+ fprintf (stderr, "Error writing to %s\n", savefile);
+ return (-1);
+ }
+ close (fd);
+
+ memcpy (bootRecord, bootProg, PartAddr);
+
+ rc = bootio (disk, WRITE, 0, 0, 1, bootRecord);
+ if (rc) {
+ fprintf (stderr, "Error %d updating boot record on disk %d\n",
+ rc, disk);
+ return (-1);
+ }
+ printf ("New boot record successfully installed.\n");
+ return (0);
+}
+
+bootio (disk, op, head, cyl, sect, buf)
+char *buf;
+{
+ return (biosdisk (op==WRITE ? 3 : 2, disk==DISK1 ? 0x80 : 0x81,
+ head, cyl, sect, 1, buf));
+}
+
+int main (argc, argv)
+char **argv;
+{
+ char *bootfile;
+ int disk2present;
+
+ printf ("Boot installer, version 1.7, Copyright (C) Serge Vakulenko\n\n");
+
+ printf ("This utility allows you to install new boot program on your\n");
+ printf ("hard disk. The usage is:\n\n");
+ printf (" bootinst [bootfile]\n\n");
+ printf ("It installs boot block from bootfile (default boot.bin) to the first\n");
+ printf ("drive and, if second drive is present, to the second drive.\n");
+ printf ("Old boot sectors are saved to bootsav.bin and boot2sav.bin respectively.\n");
+ printf ("\nYou can copy and distribute this software free of charge,\n");
+ printf ("provided that sources are included. No warranty, of course.\n\n");
+
+ if (argc > 3)
+ return (-1);
+
+ bootfile = argc>1 ? argv[1] : BOOTFILE;
+ if (access (bootfile, 4) < 0) {
+ perror (bootfile);
+ return (-1);
+ }
+
+ /*
+ * Is second disk present? Try to read boot sector,
+ * check that it is bootable and has valid partition table.
+ */
+ disk2present = (bootio (DISK2, READ, 0, 0, 1, bootRecord) == 0 &&
+ *(short *) &bootRecord [ValidationAddr] == (short) MAGIC &&
+ (bootRecord [PartAddr] == 0 || bootRecord [PartAddr] == 0x80) &&
+ (bootRecord [PartAddr+16] == 0 || bootRecord [PartAddr+16] == 0x80) &&
+ (bootRecord [PartAddr+32] == 0 || bootRecord [PartAddr+32] == 0x80) &&
+ (bootRecord [PartAddr+48] == 0 || bootRecord [PartAddr+48] == 0x80));
+
+ printf ("Continue with installation?");
+ if (! yes ())
+ return (0);
+
+ install (DISK1, bootfile, SAVEFILE);
+
+ if (disk2present)
+ install (DISK2, bootfile, SAVE2FILE);
+
+ return (0);
+}