/* >>> this is file REALBIOS.C ============================================================================ LOADLIN v1.4 (C) 1994 Hans Lermen (lermen@elserv.ffm.fgan.de) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ---------------------------------------------------------------------------- Comments and bug reports are welcome and may be sent to: E-Mail: lermen@elserv.ffm.fgan.de SnailMail: Hans Lermen Am Muehlenweg 38 D53424 REMAGEN-Unkelbach GERMANY ============================================================================ Alessandro Rubini (rubini@ipvvis.unipv.it) wrote BOOTSECT.BIN (which contains code from bootsect.S by Linus Torvalds). His way (used in his package linuxEXE ) of getting the *real* original BIOS interrupt vector is the safest way. All other solutions are too tricky. I added saving of BIOS data/scratch, PIC-IMR and TOP-ROM, but it remains essentially Alessandro's technique. My simple method (using BIOSINTV.SYS) gets an interrupt table that is slightly modified by DOS (i.e. it is NOT the *real* original), but it works for almost all configurations. It doesn't require changing the BIOS data/scratch areas, because they are mostly consistent with the interrupt vector. You should use the BIOSINTV method whenever possible. If, and only if, you don't succeed with the BIOSINTV method, try the REALBIOS method instead as a last resort. But NOTE: -------- ! The C:\REALBIOS.INT file created by the REALBIOS method is unique ! to the machine on which it is generated! It must be in C:\ . ! ! Do NOT DISTRIBUTE it to your friends (distribute only "lodlin14.tgz"). ! Do NOT COPY it from your friend's machine. ! Do NOT SHARE it (e.g. via NFS). ! Rebuild the file if you make ANY hardware changes to your machine ! (such as adding/removing an adapter card, adding/removing RAM or ! changing an IRQ or I/O address). ! Use it only on the machine it is generated on! --- -- ---- -- --- ------- -- -- --------- --- ============================================================================ */ #define REALBIOS_FILE "C:\\REALBIOS.INT" #include #include #include #include #include #include #include #include typedef unsigned char byte; enum {reset_drive,drive_status,read_sector,write_sector,verify_sector}; enum {drive_A,drive_B}; #define RETRY_MAX 5 #define space64k 0x10000 static struct { byte b[512-2-2-2]; unsigned short int realbootmagic; short int flag; unsigned short int bootmagic; void *intv[256]; /* intvector 0:0 */ byte bios_data[256]; /* BIOS-data 40:0 */ byte dummy[256-4-16-2]; /* (DOS-data 50:0, not valid at boot tome */ unsigned short int15_result; unsigned short real_bios_magic; byte jmpop; /* TOP BIOS FFFF:0 */ void *reset_entry; char biosdate[9]; byte machineid; byte dummy2; byte masterIMR; /* port 21 */ byte slaveIMR; /* port A1 */ byte bios_scratch[1024];/* scratch 9FC0:0 */ } *physbuf=0; #define PHYSBUF_SIZE sizeof(*physbuf) #define BOOTMAGIC 0xAA55 #define REALBOOTMAGIC 0xBB66 static void *init_physbuffer(unsigned short size) { union { void *p; unsigned short w[2]; }p; unsigned long l; do { p.p=malloc(size); if (!p.p) return 0; l=((long)p.w[1] << 4) + p.w[0]; } while ((l + size) > ( (l+space64k) & (~(space64k-1)) )); return p.p; } static int read_buffer() { int i,s; biosdisk(reset_drive, drive_A, 0, 0, 0, 0, physbuf); for (i=0; ibootmagic=BOOTMAGIC; physbuf->realbootmagic=REALBOOTMAGIC; close(f); return c; } static int write_realbios_file(char *name) { int f,c; if ((f=_creat(name, FA_HIDDEN | FA_SYSTEM)) == -1 ) { perror(name); exit(1); } if ((c=write(f, &physbuf->intv, PHYSBUF_SIZE-256) == -1 )) { perror(name); close(f); exit(1); }; close(f); return c; } static void print_logo() { printf( "LOADLIN v1.4 (C) 1994 Hans Lermen (lermen@elserv.ffm.fgan.de)\n" "\n" "Generation of the file " REALBIOS_FILE " (for the REALBIOS method) consists\n" "of TWO steps:\n" "\n" " 1. Generating the special boot floppy and booting with it.\n" "\n" " 2. Reading the saved interrupt table and BIOS data from the floppy\n" " and writing it to " REALBIOS_FILE "\n" "\n" "Type 1 or 2, (depending on which step you are in) or any other key to cancel:\n" ); } static void print_step1_1() { printf( "\n" "OK, we first generate the floppy !\n" "Insert an empty but DOS-formatted disk into drive A:\n" "(no matter what DOS format it is)\n" "\n" "Type C to continue or any other key to cancel\n" ); } static void print_step1_2() { printf( "\n" "OK, The special boot floppy has been generated.\n" "Leave it inserted in drive A: and reboot your machine\n" " But NOTE:\n" " If you have a disk cache program (like SMARTDRV)\n" " you may need to flush the write-behind cache first!\n" ); } static void print_step2_1() { printf( "\n" "OK, we now read the saved interrupt vector from the floppy\n" "and save it to the file " REALBIOS_FILE " (no way to change the name!)\n" "Is the floppy (used in step 1) inserted in drive A: ?\n" "\n" "Type Y to continue or any other key to cancel\n" ); } static void print_step2_2() { printf( "\n" "OK, all seems good, " REALBIOS_FILE " has been generated\n" "\n" "WARNING:\n" "! " REALBIOS_FILE " is unique to this machine !\n" "! Do NOT DISTRIBUTE it to your friends (distribute only \"lodlin14.tgz\").\n" "! Do NOT COPY it from your friend's machine.\n" "! Do NOT SHARE it (e.g. via NFS).\n" "! Rebuild the file (rerun REALBIOS) if you make ANY hardware changes to\n" "! your machine (such as adding/removing an adapter card,\n" "! adding/removing RAM or changing an IRQ or I/O address).\n" "! Use it only on THIS machine.\n" "\n" "NOTE:\n" "1. " REALBIOS_FILE " is marked HIDDEN+SYSTEM to avoid distribution.\n" "2. The special floppy is unusable for DOS, You must format it again\n" ); } static void print_diskerror(int err) { if (err == 3) printf("floppy disk is write protected\n"); else printf("floppy disk error %02x\n",err); } static void step1() { int c; print_step1_1(); c=bioskey(0) & 255; if (tolower(c) !='c') exit(1); if (c=read_buffer()) { /* check if disk is formatted */ print_diskerror(c); exit(1); } read_bootsect_bin("bootsect.bin"); if (c=write_bootsector()) { print_diskerror(c); exit(1); } print_step1_2(); } static void step2() { int c; print_step2_1(); c=bioskey(0) & 255; if (tolower(c) !='y') exit(1); if (c=read_buffer()) { print_diskerror(c); exit(1); } if ((physbuf->bootmagic != BOOTMAGIC) || (physbuf->realbootmagic != REALBOOTMAGIC)) { printf("\nWrong floppy\n" "Please repeat starting with step 1\n"); exit(1); } if (physbuf->flag != 1) { if (physbuf->flag) printf("Already-used floppy, can use our floppy only once\n" "Please repeat starting with step 1\n"); else printf("You must boot from this floppy (3-finger salute) before doing step 2\n"); exit(1); } physbuf->flag=2; if (c=write_bootsector()) { /* make the floppy unusable */ print_diskerror(c); exit(1); } write_realbios_file(REALBIOS_FILE); print_step2_2(); } main() { int c; physbuf=init_physbuffer(PHYSBUF_SIZE); print_logo(); c=bioskey(0) & 255; if (c == '1') step1(); else if (c == '2') step2(); else return 1; return 0; }