home *** CD-ROM | disk | FTP | other *** search
- /* >>> 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 <stdio.h>
- #include <alloc.h>
- #include <bios.h>
- #include <string.h>
- #include <io.h>
- #include <fcntl.h>
- #include <ctype.h>
- #include <dos.h>
-
- 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; i<RETRY_MAX; i++) {
- s=biosdisk(read_sector, drive_A, 0, 0, 1, 6, physbuf);
- if (!s) return 0;
- }
- return s;
- }
-
-
- static int write_bootsector()
- {
- int i,s;
- for (i=0; i<RETRY_MAX; i++) {
- s=biosdisk(write_sector, drive_A, 0, 0, 1, 1, physbuf);
- if (!s) return 0;
- }
- return s;
- }
-
- static int read_bootsect_bin(char *name) {
- int f,c;
- if ((f=open(name, O_RDONLY | O_BINARY)) == -1 ) {
- perror(name);
- exit(1);
- }
- memset(physbuf,0,512);
- if ((c=read(f, physbuf, 512 -2) == -1 )) {
- perror(name);
- close(f);
- exit(1);
- };
- physbuf->bootmagic=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;
- }
-