System Restore
This is a restore program designed to be boot from a CD. Once booted the program will proceed to display several images by calling the BIOS video interrupt 0x10 and then request mode 13h. Mode 13h offers 320 by 200 with 256 colors and is widely supported by nearly all video cards. The GUI was created by basically loading a new image off of disk either after a time delay or when a key was struck by a user. So for a menu, you must swap out images to stimulate that the user can scroll through the menu's selections, etc... This program's GUI menu had two choices--restore and DOS Shell. If the user chose "Restore" then the hard drive would get partitioned and then the 1st sector on the hard drive is flagged and the computer is restarted. Upon restart, the partition changes are now visible and the program detects that it was just partitioned by searching for the flag on the first sector. Then the hard drive is formatted and a compressed archive containing the Operating system is extracted.
How did I partition the drive?
I cheated...
I was fortunate to find that FreeDOS's fdisk utility had command line options so that I can interact with it without any special coding and it had the capability of setting flags(use the /SETFLAG option). The fdisk utility had the following Syntax:
Syntax: FDISK [/ACTOK] [/CMBR drive#)] [[/EXT:size drive# [{/LOG:size} |
{/LOGO:size}]] [/FPRMT] [/MBR] [/PRI:size drive#]
[/PRIO:size drive#] [/Q] [/REBOOT] [/STATUS] [/X]
Code Snippet
/* Restore.c */
#include
#include
#include
#include
#include
#include "restore.h"
#include "vga.h"
//#include "keyboard.h"
#define ESC_KEY 27
#define UP_KEY 328
#define DOWN_KEY 336
#define ENTER_KEY 13
void menu();
void menu()
{
BITMAP window;
BITMAP b1g;
BITMAP b1y;
BITMAP b2g;
BITMAP b2y;
BITMAP bmp2;
int keypressed, selection = 0;
load_bmp("digi3.bmp", &bmp2);
draw_bitmap(&bmp2, 0,0);
set_palette(bmp2.palette);
// Load Window
load_bmp("window.bmp", &window);
//Load Buttons
load_bmp("b1g.bmp", &b1g);
load_bmp("b1y.bmp", &b1y);
load_bmp("b2g.bmp", &b2g);
load_bmp("b2y.bmp", &b2y);
draw_bitmap(&window,70,50);
set_palette(window.palette);
//wait_for_retrace();
draw_transparent_bitmap(&b1g,90, 60);
set_palette(b1g.palette);
//wait_for_retrace();
draw_transparent_bitmap(&b2g,90, 105);
set_palette(b2g.palette);
wait_for_retrace();
// set_palette(window.palette);
while(1){
keypressed = getkey();
switch(keypressed){
case ESC_KEY:
{
deinit_video();
exit(EXIT_SUCCESS);
}
break;
case UP_KEY:
{
selection = 1;
draw_bitmap(&window,70,50);
draw_transparent_bitmap(&b2g,90, 105);
//set_palette(b2g.palette);
//wait_for_retrace();
draw_transparent_bitmap(&b1y,90, 60);
set_palette(b1y.palette);
wait_for_retrace();
}
break;
case DOWN_KEY:
{
selection = 2;
draw_bitmap(&window,70,50);
draw_transparent_bitmap(&b1g,90, 60);
//set_palette(b1g.palette);
//wait_for_retrace();
draw_transparent_bitmap(&b2y,90, 105);
set_palette(b2y.palette);
wait_for_retrace();
}
break;
case ENTER_KEY:
{
if(selection == 1) system("eval.bat"); //Starts restore
if(selection == 2) system("command.com"); // Starts DOS Shell
}
break;
default:
break;
}
//printf("\nkey = %d", keypressed); //Key Check
}
deinit(window);
deinit(b1g);
deinit(b2g);
deinit(b1y);
deinit(b2y);
return;
}
int main()
{
BITMAP bmp1;
init();
load_bmp("fire.bmp", &bmp1);
draw_bitmap(&bmp1, 0,0);
set_palette(bmp1.palette);
// bitmap_linear_interpolation( "digifire.raw", "digi3.raw", 1);
//set_palette(bmp1.palette);
wait(10);
menu();
// deinit(bmp1);
return 0;
}
/////////////////////////////////////////////////////////////////////////
restore.h
#ifndef __RESTORE_H__
#define __RESTORE_H__
#include "vga.h"
#define START_BMP ("digi.sys")
#define ERROR 0
#define SUCCESS 1
void init();
void deinit();
int check_MBR_flag();
int delete_partition();
int create_partition();
void Reboot_PC();
void init()
{
int i;
if( __djgpp_nearptr_enable() == 0){
printf("\nCould not get access to first 640k of memory.\n");
exit(EXIT_FAILURE);
}
VGA+= __djgpp_conventional_base;
my_clock = (void *)my_clock + __djgpp_conventional_base;
set_mode(VGA_256_COLOR_MODE);
//memset( &VGA, 0, 64000 );
//for( i = 0; i < SCREEN_HEIGHT; i++)
// memset(&VGA[SCREEN_WIDTH*i], i, SCREEN_WIDTH);
}
void deinit(BITMAP digi_pic)
{
free(digi_pic.data);
set_mode(TEXT_MODE);
__djgpp_nearptr_disable();
}
int check_MBR_flag()
{
system("EVAL.BAT");
}
int delete_partition()
{
system("FDISK.EXE /CLEAR");
}
int create_partition()
{
system("FDISK.EXE /PRI:9000000000 /ACTIVATE:1");
system("FDISK.EXE /MODIFY:1,11");
}
void Reboot_PC()
{
/* Note: Reboot is a cold start. */
//void ( (far* fp)() ) = (void(far*) () ) ((0xffffL<<16) | 0x0000L);
//*(int far *) ((0x0040L << 16) | 0x0072)=0;
//fp();
system("/FDISK/FDISK.EXE /REBOOT");
}
#endif
/////////////////////////////////////////////////////////////////////////
video.h
/* video.h */
#include
#include
#include
#include
#include
#include
/*
*
*
*
*/
#define VIDEO_INT 0x10
#define SET_MODE 0x00
#define VGA_256_COLOR_MODE 0x13
#define TEXT_MODE 0x03
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 200
#define NUM_COLORS 256
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
byte *VGA = (byte *) 0xA0000;
word *my_clock = (word *)0x046C;
typedef struct tagBITMAP { /* Structure of a Basic Bitmap */
word width;
word height;
byte *data;
} BITMAP;
void set_mode(byte mode);
void fskip( FILE *fp, int num_bytes);
void setpixel(int x, int y, unsigned char color);
void setcolor(char color, char r, char g, char b);
void draw_line(int x1, int y1, int x2, int y2, unsigned char color);
void load_bmp( char *file, BITMAP *b);
void draw_bitmap(BITMAP *bmp, int x, int y);
void wait(int ticks); /* Waits for specified number of ticks */
void text_mode(void);
void set_mode(byte mode)
{
union REGS regs;
regs.h.ah = SET_MODE;
regs.h.al = mode;
int86(VIDEO_INT, ®s, ®s);
}
void text_mode(void)
{
set_mode(TEXT_MODE);
}
void setpixel(int x, int y, unsigned char color)
{
_farpokeb(_dos_ds, 0xA0000 + x + (y << 6) + (y << 8), color);
}
void setcolor(char color, char r, char g, char b)
{
outportb(0x3c8, color);
outportb(0x3c9, r);
outportb(0x3c9, g);
outportb(0x3c9, b);
}
void draw_line(int x1, int y1, int x2, int y2, unsigned char color)
{
float a, b = y1, dx, dy, DX, DY;
DX = x2 - x1;
DY = y2 - y1;
for( a = x1; a <= x2; a++){
dx = a - x1;
dy = (DY / DX) * dx;
setpixel( (int) a, (int) (b + dy), color);
}
}
void load_bmp( char *file, BITMAP *b)
{
FILE *fp;
long index;
word num_colors;
int x;
if( (fp = fopen(file, "rb")) == NULL){
printf("\nError opening file %s.", file);
exit(EXIT_FAILURE);
}
if( fgetc(fp) != 'B' || fgetc(fp) != 'M'){
fclose(fp);
printf("\n%s is not a bitmap file.", file);
exit(EXIT_FAILURE);
}
fskip( fp, 16);
fread( &b->width, sizeof(word), 1, fp);
fskip( fp, 2);
fread( &b->height, sizeof(word), 1, fp);
fskip( fp, 22);
fread( &num_colors, sizeof(word), 1, fp);
fskip( fp, 6);
if( num_colors == 0) num_colors = 256;
if( (b->data = (byte *) malloc( (word)(b->width*b->height))) == NULL){
fclose(fp);
printf("\nError allocating memory for file %s,", file);
exit(EXIT_FAILURE);
}
/* skip palette info */
fskip( fp, num_colors * 4);
/* read the bitmap */
for( index = (b->height - 1) * b->width; index >= 0; index-=b->width)
for(x = 0; x < b->width; x++)
b->data[(word) index + x] = (byte) fgetc(fp);
fclose(fp);
}
void draw_bitmap(BITMAP *bmp, int x, int y)
{
int j;
word screen_offset = (y << 8) + (y << 6) + x;
word bitmap_offset = 0;
byte data;
for( j = 0; j < bmp->height; j++){
memcpy( &VGA[screen_offset], &bmp->data[bitmap_offset], bmp->width);
bitmap_offset += bmp->width;
screen_offset += SCREEN_WIDTH;
}
}
void fskip( FILE *fp, int num_bytes)
{
int i;
for( i = 0; i < num_bytes; i++)
fgetc(fp);
}
void wait(int ticks)
{
word start;
start = *my_clock;
while( *my_clock - start < ticks){
*my_clock = *my_clock; /*Some Compilers would ignore this
if it weren't for this line. */
}
}
#endif