home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / KERNELS / LODLIN15.ZIP / LOADLIN / REALBIOS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-16  |  9.1 KB  |  318 lines

  1. /*  >>> this is file REALBIOS.C
  2. ============================================================================
  3.    LOADLIN v1.4 (C) 1994 Hans Lermen (lermen@elserv.ffm.fgan.de)
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2 of the License, or
  8.    (at your option) any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. ----------------------------------------------------------------------------
  20.    Comments and bug reports are welcome and may be sent to:
  21.    E-Mail:    lermen@elserv.ffm.fgan.de
  22.    SnailMail: Hans Lermen
  23.               Am Muehlenweg 38
  24.               D53424 REMAGEN-Unkelbach
  25.               GERMANY
  26.  
  27. ============================================================================
  28.  
  29.  
  30.    Alessandro Rubini (rubini@ipvvis.unipv.it) wrote BOOTSECT.BIN (which
  31.    contains code from bootsect.S by Linus Torvalds).
  32.  
  33.    His way (used in his package linuxEXE ) of getting the *real* original
  34.    BIOS interrupt vector is the safest way.  All other solutions are too
  35.    tricky.  I added saving of BIOS data/scratch, PIC-IMR and TOP-ROM, but
  36.    it remains essentially Alessandro's technique.
  37.  
  38.    My simple method (using BIOSINTV.SYS) gets an interrupt table that is
  39.    slightly modified by DOS (i.e. it is NOT the *real* original), but it
  40.    works for almost all configurations. It doesn't require changing the
  41.    BIOS data/scratch areas, because they are mostly consistent with the
  42.    interrupt vector.  You should use the BIOSINTV method whenever possible.
  43.  
  44.  
  45.    If, and only if, you don't succeed with the BIOSINTV method, try the
  46.    REALBIOS method instead as a last resort.
  47.  
  48.    But NOTE:
  49.    --------
  50.    !  The  C:\REALBIOS.INT  file created by the REALBIOS method is unique
  51.    !  to the machine on which it is generated!  It must be in C:\ .
  52.    !
  53.    !  Do NOT DISTRIBUTE it to your friends (distribute only "lodlin14.tgz").
  54.    !  Do NOT COPY it from your friend's machine.
  55.    !  Do NOT SHARE it (e.g. via NFS).
  56.    !  Rebuild the file if you make ANY hardware changes to your machine
  57.    !   (such as adding/removing an adapter card, adding/removing RAM or
  58.    !    changing an IRQ or I/O address).
  59.    !  Use it only on the machine it is generated on!
  60.       --- -- ---- -- --- ------- -- -- --------- ---
  61.  
  62.  
  63.  
  64. ============================================================================ */
  65.  
  66. #define REALBIOS_FILE "C:\\REALBIOS.INT"
  67.  
  68. #include <stdio.h>
  69. #include <alloc.h>
  70. #include <bios.h>
  71. #include <string.h>
  72. #include <io.h>
  73. #include <fcntl.h>
  74. #include <ctype.h>
  75. #include <dos.h>
  76.  
  77. typedef unsigned char byte;
  78.  
  79.  
  80. enum {reset_drive,drive_status,read_sector,write_sector,verify_sector};
  81. enum {drive_A,drive_B};
  82. #define RETRY_MAX  5
  83.  
  84. #define space64k 0x10000
  85.  
  86. static struct {
  87.   byte b[512-2-2-2];
  88.   unsigned short int realbootmagic;
  89.   short int flag;
  90.   unsigned short int bootmagic;
  91.   void *intv[256];        /* intvector  0:0 */
  92.   byte bios_data[256];    /* BIOS-data 40:0 */
  93.   byte dummy[256-4-16-2];   /* (DOS-data  50:0, not valid at boot tome */
  94.   unsigned short int15_result;
  95.   unsigned short real_bios_magic;
  96.   byte jmpop;             /* TOP BIOS FFFF:0 */
  97.   void *reset_entry;
  98.   char biosdate[9];
  99.   byte machineid;
  100.   byte dummy2;
  101.   byte masterIMR;         /* port 21 */
  102.   byte slaveIMR;          /* port A1 */
  103.   byte bios_scratch[1024];/* scratch  9FC0:0 */
  104. } *physbuf=0;
  105. #define PHYSBUF_SIZE sizeof(*physbuf)
  106.  
  107. #define BOOTMAGIC 0xAA55
  108. #define REALBOOTMAGIC 0xBB66
  109.  
  110. static void *init_physbuffer(unsigned short size) {
  111.   union {
  112.     void *p;
  113.     unsigned short w[2];
  114.   }p;
  115.   unsigned long l;
  116.   do {
  117.     p.p=malloc(size);
  118.     if (!p.p) return 0;
  119.     l=((long)p.w[1] << 4) + p.w[0];
  120.   } while ((l + size) > ( (l+space64k) & (~(space64k-1)) ));
  121.   return p.p;
  122. }
  123.  
  124.  
  125. static int read_buffer()
  126. {
  127.   int i,s;
  128.   biosdisk(reset_drive, drive_A, 0, 0, 0, 0, physbuf);
  129.   for (i=0; i<RETRY_MAX; i++) {
  130.     s=biosdisk(read_sector, drive_A, 0, 0, 1, 6, physbuf);
  131.     if (!s) return 0;
  132.   }
  133.   return s;
  134. }
  135.  
  136.  
  137. static int write_bootsector()
  138. {
  139.   int i,s;
  140.   for (i=0; i<RETRY_MAX; i++) {
  141.     s=biosdisk(write_sector, drive_A, 0, 0, 1, 1, physbuf);
  142.     if (!s) return 0;
  143.   }
  144.   return s;
  145. }
  146.  
  147. static int read_bootsect_bin(char *name) {
  148.   int f,c;
  149.   if ((f=open(name, O_RDONLY | O_BINARY)) == -1 ) {
  150.      perror(name);
  151.      exit(1);
  152.   }
  153.   memset(physbuf,0,512);
  154.   if ((c=read(f, physbuf, 512 -2) == -1 )) {
  155.      perror(name);
  156.      close(f);
  157.      exit(1);
  158.   };
  159.   physbuf->bootmagic=BOOTMAGIC;
  160.   physbuf->realbootmagic=REALBOOTMAGIC;
  161.   close(f);
  162.   return c;
  163. }
  164.  
  165. static int write_realbios_file(char *name) {
  166.   int f,c;
  167.   if ((f=_creat(name, FA_HIDDEN | FA_SYSTEM)) == -1 ) {
  168.      perror(name);
  169.      exit(1);
  170.   }
  171.   if ((c=write(f, &physbuf->intv, PHYSBUF_SIZE-256) == -1 )) {
  172.      perror(name);
  173.      close(f);
  174.      exit(1);
  175.   };
  176.   close(f);
  177.   return c;
  178. }
  179.  
  180. static void print_logo()
  181. {
  182.   printf(
  183.     "LOADLIN v1.4 (C) 1994 Hans Lermen (lermen@elserv.ffm.fgan.de)\n"
  184.     "\n"
  185.     "Generation of the file " REALBIOS_FILE " (for the REALBIOS method) consists\n"
  186.     "of TWO steps:\n"
  187.     "\n"
  188.     "  1. Generating the special boot floppy and booting with it.\n"
  189.     "\n"
  190.     "  2. Reading the saved interrupt table and BIOS data from the floppy\n"
  191.     "     and writing it to " REALBIOS_FILE "\n"
  192.     "\n"
  193.     "Type 1 or 2, (depending on which step you are in) or any other key to cancel:\n"
  194.   );
  195. }
  196.  
  197. static void print_step1_1()
  198. {
  199.   printf(
  200.     "\n"
  201.     "OK, we first generate the floppy !\n"
  202.     "Insert an empty but DOS-formatted disk into drive A:\n"
  203.     "(no matter what DOS format it is)\n"
  204.     "\n"
  205.     "Type C to continue or any other key to cancel\n"
  206.   );
  207. }
  208.  
  209. static void print_step1_2()
  210. {
  211.   printf(
  212.     "\n"
  213.     "OK, The special boot floppy has been generated.\n"
  214.     "Leave it inserted in drive A: and reboot your machine\n"
  215.     "  But NOTE:\n"
  216.     "  If you have a disk cache program (like SMARTDRV)\n"
  217.     "  you may need to flush the write-behind cache first!\n"
  218.   );
  219. }
  220.  
  221. static void print_step2_1()
  222. {
  223.   printf(
  224.     "\n"
  225.     "OK, we now read the saved interrupt vector from the floppy\n"
  226.     "and save it to the file " REALBIOS_FILE " (no way to change the name!)\n"
  227.     "Is the floppy (used in step 1) inserted in drive A: ?\n"
  228.     "\n"
  229.     "Type Y to continue or any other key to cancel\n"
  230.   );
  231. }
  232.  
  233. static void print_step2_2()
  234. {
  235.   printf(
  236.     "\n"
  237.     "OK, all seems good, " REALBIOS_FILE " has been generated\n"
  238.     "\n"
  239.     "WARNING:\n"
  240.     "!  " REALBIOS_FILE " is unique to this machine !\n"
  241.     "!  Do NOT DISTRIBUTE it to your friends (distribute only \"lodlin14.tgz\").\n"
  242.     "!  Do NOT COPY it from your friend's machine.\n"
  243.     "!  Do NOT SHARE it (e.g. via NFS).\n"
  244.     "!  Rebuild the file (rerun REALBIOS) if you make ANY hardware changes to\n"
  245.     "!  your machine (such as adding/removing an adapter card,\n"
  246.     "!  adding/removing RAM or changing an IRQ or I/O address).\n"
  247.     "!  Use it only on THIS machine.\n"
  248.     "\n"
  249.     "NOTE:\n"
  250.     "1. " REALBIOS_FILE " is marked HIDDEN+SYSTEM to avoid distribution.\n"
  251.     "2. The special floppy is unusable for DOS, You must format it again\n"
  252.   );
  253. }
  254.  
  255. static void print_diskerror(int err) {
  256.   if (err == 3) printf("floppy disk is write protected\n");
  257.   else printf("floppy disk error %02x\n",err);
  258. }
  259.  
  260. static void step1()
  261. {
  262.   int c;
  263.   print_step1_1();
  264.   c=bioskey(0) & 255;
  265.   if (tolower(c) !='c') exit(1);
  266.   if (c=read_buffer()) {  /* check if disk is formatted */
  267.     print_diskerror(c);
  268.     exit(1);
  269.   }
  270.   read_bootsect_bin("bootsect.bin");
  271.   if (c=write_bootsector()) {
  272.     print_diskerror(c);
  273.     exit(1);
  274.   }
  275.   print_step1_2();
  276. }
  277.  
  278. static void step2()
  279. {
  280.   int c;
  281.   print_step2_1();
  282.   c=bioskey(0) & 255;
  283.   if (tolower(c) !='y') exit(1);
  284.   if (c=read_buffer()) {
  285.     print_diskerror(c);
  286.     exit(1);
  287.   }
  288.   if ((physbuf->bootmagic != BOOTMAGIC) || (physbuf->realbootmagic != REALBOOTMAGIC)) {
  289.     printf("\nWrong floppy\n"
  290.            "Please repeat starting with step 1\n");
  291.     exit(1);
  292.   }
  293.   if (physbuf->flag != 1) {
  294.     if (physbuf->flag) printf("Already-used floppy, can use our floppy only once\n"
  295.                               "Please repeat starting with step 1\n");
  296.     else printf("You must boot from this floppy (3-finger salute) before doing step 2\n");
  297.     exit(1);
  298.   }
  299.   physbuf->flag=2;
  300.   if (c=write_bootsector()) {   /* make the floppy unusable */
  301.     print_diskerror(c);
  302.     exit(1);
  303.   }
  304.   write_realbios_file(REALBIOS_FILE);
  305.   print_step2_2();
  306. }
  307.  
  308. main() {
  309.   int c;
  310.   physbuf=init_physbuffer(PHYSBUF_SIZE);
  311.   print_logo();
  312.   c=bioskey(0) & 255;
  313.   if (c == '1') step1();
  314.   else if (c == '2') step2();
  315.   else return 1;
  316.   return 0;
  317. }
  318.