/* 
    FIPS - the First nondestructive Interactive Partition Splitting program 
    Module restorrb.c 
 
    Copyright (C) 1993 Arno Schaefer 
 
    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 1, 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. 
*/ 
 
#include <stdio.h> 
#include <io.h> 
#include <stdlib.h> 
#include <dos.h> 
#include <bios.h> 
#include <alloc.h> 
#include <conio.h> 
#include <ctype.h> 
 
#include "rtypes.h" 
 
#define DISK_INT 0x13 
 
#define RESET_DISK 0 
#define WRITE_SECTOR 3 
#define VERIFY_SECTOR 4 
 
#define DISK1 0x80 
 
/* ----------------------------------------------------------------------- */ 
/* Copyright notice and version number                                     */ 
/* ----------------------------------------------------------------------- */ 
 
void notice (void) 
{ 
	printf ("\nFIPS version 1.1, Copyright (C) 1993/94 Arno Schaefer\n"); 
	printf ("Module RESTORRB.EXE - Please read the file README.1ST\n"); 
	printf ("FIPS comes with ABSOLUTELY NO WARRANTY, see file COPYING for details\n"); 
	printf ("This is free software, and you are welcome to redistribute it\n"); 
	printf ("under certain conditions; again see file COPYING for details.\n"); 
} 
 
/* ----------------------------------------------------------------------- */ 
/* Error Handling                                                          */ 
/* ----------------------------------------------------------------------- */ 
 
int getx (void) 
{ 
	int character = getch(); 
 
	if (character == 3) 
	{ 
		printf ("\n"); 
		exit (0); 
	} 
	return (character); 
} 
 
void error (char *message) 
{ 
	fprintf (stderr,"\nError: %s!\n",message); 
	exit (-1); 
} 
 
/* ----------------------------------------------------------------------- */ 
/* BIOS calls                                                              */ 
/* ----------------------------------------------------------------------- */ 
 
int reset_drives (void) 
{ 
	union REGS regs; 
 
	regs.h.ah = RESET_DISK; 
	regs.h.dl = DISK1; 
	int86 (DISK_INT,&regs,&regs); 
	if (regs.x.cflag) return (-1); 
	return 0; 
} 
 
/* ----------------------------------------------------------------------- */ 
/* read / write sectors                                                    */ 
/* ----------------------------------------------------------------------- */ 
 
int verify_sector (int drive_number,dword head,dword cylinder,dword sector,byte *buffer) 
{ 
	if (biosdisk (VERIFY_SECTOR,drive_number,head,cylinder,sector,1,buffer)) return (-1); 
	return 0; 
} 
 
int write_sector (int drive_number,dword head,dword cylinder,dword sector,byte *buffer) 
{ 
	int i; 
	boolean done=false; 
	for (i=0;i<3;i++) 
	{ 
		if (!biosdisk (WRITE_SECTOR,drive_number,head,cylinder,sector,1,buffer)) 
		{ 
			done=true; 
			break; 
		} 
		reset_drives(); 
	} 
	if (!done) return (-1); 
	return (verify_sector (drive_number,head,cylinder,sector,buffer)); 
} 
 
int write_root_sector (int drive_number,byte *buffer) 
{ 
	return (write_sector (drive_number,0,0,1,buffer)); 
} 
 
/* ----------------------------------------------------------------------- */ 
/* User Input                                                              */ 
/* ----------------------------------------------------------------------- */ 
 
void ask_for_write_permission (void) 
{ 
	int character = 'x'; 
 
	printf ("\nReady to write old root- and bootsector to disk\n"); 
	printf ("Do you want to proceed (y/n): "); 
 
	while ((character != 'y') && (character != 'n')) character = getx(); 
	printf ("%c\n",character); 
	if (character == 'n') exit (0); 
} 
 
/* ----------------------------------------------------------------------- */ 
/* Main                                                                    */ 
/* ----------------------------------------------------------------------- */ 
 
void main (void) 
{ 
	byte rootsector[512]; 
	byte bootsector[512]; 
	int drive_number,partition_number,i; 
	FILE *handle; 
	dword head,cylinder,sector; 
	char *filename = "a:\\rootboot.000"; 
	int no_of_savefiles = 0; 
	char first = 'x'; 
 
	notice(); 
 
	if (reset_drives ()) error ("Drive Initialization Failure"); 
 
	for (i='0';i<='9';i++) 
	{ 
		filename[14] = i; 
		if (access (filename,0) == 0) 
		{ 
			if (first == 'x') first = i; 
			no_of_savefiles++; 
			printf ("found savefile %s\n",filename); 
		} 
	} 
 
	if (no_of_savefiles == 0) error ("No savefile ROOTBOOT.00? found on disk A:"); 
 
	if (no_of_savefiles > 1) 
	{ 
		printf ("\nWhich file do you want to restore? "); 
		while (true) 
		{ 
			int c; 
			if (isdigit (c = getx())) 
			{ 
				filename[14] = c; 
				if (access (filename,0) == 0) break; 
			} 
		} 
	} 
	else 
	{ 
		filename[14] = first; 
	} 
 
	if (no_of_savefiles > 1) 
	{ 
		printf ("%c\n", filename[14]); 
	} 
 
	if ((handle = fopen (filename,"rb")) == NULL) 
		error ("Can't open file"); 
 
	for (i=0;i<512;i++) 
	{ 
		int character = fgetc (handle); 
		if (character == EOF) error ("Error reading file from disk"); 
		*(rootsector + i) = character; 
	} 
	for (i=0;i<512;i++) 
	{ 
		int character = fgetc (handle); 
		if (character == EOF) error ("Error reading file from disk"); 
		*(bootsector + i) = character; 
	} 
	if ((drive_number = fgetc (handle)) == EOF) error ("Error reading file from disk"); 
	if ((partition_number = fgetc (handle)) == EOF) error ("Error reading file from disk"); 
	if (fclose (handle)) error ("Error closing file"); 
 
	head = (dword) rootsector[0x1be+16*partition_number+1]; 
	cylinder = (((dword) rootsector[0x1be+16*partition_number+2] << 2) & 0x300) 
		| (dword) rootsector[0x1be+16*partition_number+3]; 
	sector = (dword) rootsector[0x1be+16*partition_number+2] & 0x3f; 
 
	ask_for_write_permission(); 
 
	if (write_root_sector (drive_number,rootsector)) 
		error ("Error writing rootsector"); 
 
	if (write_sector (drive_number,head,cylinder,sector,bootsector)) 
		error ("Error writing bootsector"); 
} 
