#ifndef __fdiskio_h
#define __fdiskio_h
/* FDISK IO Christopher Robert Evans (c) 2005 gryphonphyre@gamebox.net
 */

typedef struct _partitionblock {
        unsigned char pnBOOT, pnBEGHEAD;
        unsigned int pnBEG_SE_CYL;
        unsigned char pnSYSCODE, pnENDHEAD;
        unsigned int pnENDSECYL;
        unsigned long int pnSTARTSEC, pnSIZE;
	} partition_entry;

unsigned char partition_sector[512];
partition_entry partition[4];
int activepart;
int changes=0;

char *type(int type) {
char *msg;
        switch(type) {
        case 0x00 : return("empty partition");
        case 0x01 : return("FAT12");
        case 0x02 : return("XENIX root");
        case 0x03 : return("XENIX /usr (obsolete)");
        case 0x04 : return("FAT16");
        case 0x05 : return("DOS 3.3+ Extended");
        case 0x06 : return("FAT16 LFS (DOS 3.31+)");
        case 0x07 : return("OS/2 IFS (HPFS), NTFS, Advanced Unix(!), QNX2.x");
        case 0x08 : return("OS/2 (v1.0-1.3), AIX boot, SplitDrive, Commodore DOS, DELL Multi-Drive Span, QNX (qny)");
        case 0x09 : return("AIX data, Coherent, QNX (qnz)");
        case 0x0A : return("OS/2 Boot Manager, Coherent SWAP, OPUS");
        case 0x0B : return("Windows95 OSR2 FAT32");
        case 0x0C : return("Windows95 OSR2 FAT32: LBA mapped");
        case 0x0E : return("Windows95 VFAT/FAT-16: LBA mapped");
        case 0x0F : return("Windows95 Extended: LBA mapped");
        case 0x10 : return("OPUS");
        case 0x11 : return("OS/2 hidden FAT12 boot, Leading Edge DOS 3.x LSF");
        case 0x12 : return("Compaq Dianostics");
        case 0x14 : return("Novell DOS 7.0 FDISK, OS/2 Boot Manager hidden FAT-16");
        case 0x16 : return("OS/2 Boot Manager hidden BIG FAT-16");
        case 0x17 : return("OS/2 Boot Manager hidden HPFS, Hidden NTFS");
        case 0x18 : return("AST Special Windows Zero-Volt Suspend SWAP");
        case 0x19 : return("Willowtech Photon coS");
        case 0x1B : return("Windows95 FAT-32 (Hidden)");
        case 0x1C : return("Windows95 FAT-32 (Hidden) using LBA mode INT13");
        case 0x1E : return("LBA VFAT (Hidden)");
        case 0x20 : return("Willowsoft Overture File System (OFS1)");
        case 0x21 : return("officially reserved, FSo2");
        case 0x23 : return("officially reserved");
        case 0x24 : return("NEC MS-DOS 3.x");
        case 0x26 : return("officially reserved");
        case 0x31 : return("officially reserved");
        case 0x33 : return("officially reserved");
        case 0x34 : return("officially reserved");
        case 0x36 : return("officially reserved");
        case 0x38 : return("Theos");
        case 0x3C : return("PowerQuest Partition Magic (recovery)");
        case 0x40 : return("VENIX 80286");
        case 0x41 : return("Personal RISC Boot, PowerPC Boot");
        case 0x42 : return("SFS (Secure File System) by Peter Gutmann");
        case 0x45 : return("EUMEL/Elan");
        case 0x46 : return("EUMEL/Elan");
        case 0x47 : return("EUMEL/Elan");
        case 0x48 : return("EUMEL/Elan");
        case 0x4F : return("Oberon boot/data");
        case 0x50 : return("OnTrack Disk Manager (read-only)");
        case 0x51 : return("OnTrack Disk Manager (read-write), NOVELL");
        case 0x52 : return("CP/M, Microport System V/386");
        case 0x53 : return("OnTrack Disk Manager (write-only)");
        case 0x54 : return("OnTrack Disk Manager (DDO)");
        case 0x55 : return("EZ-Drive");
        case 0x56 : return("GoldenBow VFeature");
        case 0x5C : return("Priam EDISK");
        case 0x61 : return("SpeedStor");
        case 0x63 : return("Unix SysV/386, 385/ix, Mach, MtXinu BSD 4.3, GNU HURD");
        case 0x64 : return("Novell NetWare 286, SpeedStore");
        case 0x65 : return("Novell NetWare 3.11");
        case 0x67 : return("Novell");
        case 0x68 : return("Novell");
        case 0x69 : return("Novell");
        case 0x70 : return("DiskSecure Multi-Boot");
        case 0x71 : return("officially reserved");
        case 0x73 : return("officially reserved");
        case 0x74 : return("officially reserved");
        case 0x75 : return("PC/IX");
        case 0x76 : return("officially reserved");
        case 0x7E : return("F.I.X.");
        case 0x80 : return("MINIX v1.1-1.4a");
        case 0x81 : return("MINIX 1.4b+, Linux, Mitac Advanced Disk Manager");
        case 0x82 : return("Linux SWAP, Prime, Solaris (Unix)");
        case 0x83 : return("Linux ext2fs/xiafs");
        case 0x84 : return("OS/2-renumbered FAT-16");
        case 0x85 : return("Linux EXT 86h FAT16 volume/stripe set (Windows NT)");
        case 0x87 : return("HPFS Fault-Tolerant mirror, NTFS volume/stripe set");
        case 0x93 : return("Amoeba file system");
        case 0x94 : return("Amoeba bad block table");
        case 0x98 : return("Datalight ROM-DOS SuperBoot");
        case 0x99 : return("Mylex EISA SCSI");
        case 0xA0 : return("Phoenix NoteBIOS Power Management 'Save-to-Disk'");
        case 0xA1 : return("officially reserved");
        case 0xA3 : return("officially reserved");
        case 0xA4 : return("officially reserved");
        case 0xA5 : return("FreeBSD, BSD/386");
        case 0xA6 : return("OpenBSD");
        case 0xA9 : return("NetBSD (http://www.netbsd.org/)");
        case 0xB1 : return("officially reserved");
        case 0xB3 : return("officially reserved");
        case 0xB4 : return("officially reserved");
        case 0xB6 : return("Windows NT master mirror set, FAT 16");
        case 0xB7 : return("BSDI secondary swap, Windows NT master mirror set, NTFS");
        case 0xB8 : return("BSDI secondary swap");
        case 0xBE : return("Solaris boot partition");
        case 0xC0 : return("DR DOS/DR-DOS/Novell DOS secured, CTOS");
        case 0xC1 : return("DR DOS 6.0 LOGIN.EXE-secured FAT-12");
        case 0xC4 : return("DR DOS 6.0 LOGIN.EXE-secured FAT-16");
        case 0xC6 : return("DR DOS 6.0 LOGIN.EXE-secured Huge, Corrupted FAT16 volume/stripe/slave mirror set (WINNT)");
        case 0xC7 : return("Syrinx Boot, corrupted NTFS volume/stripe set, Windows NT NTFS mirror set (slave)");
        case 0xCB : return("Reserved for DR DOS/DR-DOS/OpenDOS secured FAT32");
        case 0xCC : return("Reserved for DR DOS/DR-DOS secured FAT32 (LBA)");
        case 0xCE : return("Reserved for DR DOS/DR-DOS secured FAT16 (LBA)");
        case 0xD0 : return("Multiuser DOS secured FAT12");
        case 0xD1 : return("Old Multiuser DOS secured FAT12");
        case 0xD4 : return("Old Multiuser DOS secured FAT16");
        case 0xD5 : return("Old Multiuser DOS secured extended partition");
        case 0xD6 : return("Old Multiuser DOS secured BIG FAT16");
        case 0xD8 : return("CP/M-86");
        case 0xDB : return("CP/M, Concurrent CP/M/DOS, CTOS (Convergent Technologies OS)");
        case 0xE1 : return("SpeedStor FAT-12 extended");
        case 0xE2 : return("DOS read-only (Florian Painke's XFDISK 1.0.4)");
        case 0xE3 : return("Storage Dimensions, DOS read-only");
        case 0xE4 : return("SpeedStor FAT-16 extended");
        case 0xE5 : return("officially reserved");
        case 0xE6 : return("officially reserved");
        case 0xEB : return("BeOS BFS (BFS1)");
        case 0xF0 : return("Linux/PA-RISC Boot Loader");
        case 0xF1 : return("Storage Dimensions");
        case 0xF2 : return("DOS 3.3+ secondary");
        case 0xF3 : return("officially reserved");
        case 0xF4 : return("SpeedStor, Storage Dimensions");
        case 0xF5 : return("Prologue");
        case 0xF6 : return("officially reserved");
        case 0xF9 : return("pCache, OSG EFAT");
        case 0xFA : return("Bochs");
        case 0xFB : return("VMware File System");
        case 0xFC : return("VMware Swap");
        case 0xFD : return("Linux raid partition");
        case 0xFE : return("LANstep, Linux LVM (old), IBM PS/2 Initial Microcode Load");
        case 0xFF : return("Xenix bad block table ");
        default   : sprintf(msg,"Unknown Type %xH",type);
                    return(msg);
                }
}

void save_mbr(char *filename) {
FILE *handle;

        handle = fopen(filename,"w");
	if (handle == NULL) { printf("\n\r Error creating %s.",filename);
           } else {
           if (fwrite(partition_sector,512,1,handle) != 1) {
              printf("\n\r Error writing %s",filename);
              }
              fclose(handle);
           }
}
void restore_mbr(char *filename) {
FILE *handle;

        handle = fopen(filename,"r");
        if (handle == NULL) {
           printf("\n\r Unable to open %s.",filename);
           } else {
           if (fread(partition_sector,512,1,handle) == 1) { }
           fclose(handle);
           }
}

void  intergrate_entries(void) {
    if (memcpy((partition_sector+0x1BE),partition,16 * 4) == NULL) {
       printf("\n\r Error copying partition entries into Master Boot Record/n/r");
       exit(3);
       }
}
void  extract_entries(void) {
    if (memcpy(partition,(partition_sector+0x1BE),16 * 4) == NULL) {
       printf("\n\r Error loading partition entries into RAM/n/r");
       exit(2);
       }
}

void savepartition(int drive) {
unsigned char result;
    intergrate_entries();
    result = biosdisk(2,drive,0,0,1,1,partition_sector); /* read func */
    if (result != 0) { /* & 0XFF00 != 0 && error < 5) */
       printf("\n\r Error reading fixed disk\n\r");
       exit(1);
          }
}
void loadpartition(int drive) {
unsigned char result;
    /* Load partition table from disk  */
    /*sector 1 head 0 cylinder 0 first IDE*/
    result = biosdisk(2,drive,0,0,1,1,partition_sector); /* read func */
    if (result != 0) { /* & 0XFF00 != 0 && error < 5) */
       printf("\n\r Error reading fixed disk\n\r");
       exit(1);
          }
    extract_entries();
}

void  display_partitions(void) {
int i;
       for(i = 0; i < 4; i++)  {
                unsigned long int sectors = 0;
                unsigned long int tally;
                unsigned long int t[4];

                highvideo(); printf("%d",i+1); lowvideo();
                if (partition[i].pnBOOT == 0x80) {
                   printf(" BOOT "); activepart=i; } else { printf("      "); }
                printf("%6s \n\r",type(partition[i].pnSYSCODE));
                printf("\t");
                printf("%6d ",partition[i].pnBEGHEAD);
                printf("%5d ",partition[i].pnBEG_SE_CYL>>8 + (partition[i].pnBEG_SE_CYL<<2)&0x0300);
                printf("%6d ",partition[i].pnBEG_SE_CYL&0x003F);
                printf("%6d ",partition[i].pnENDHEAD);
                printf("%5d ",partition[i].pnENDSECYL>>8 +(partition[i].pnENDSECYL<<2)&0x0300);
		printf("%6d ",partition[i].pnBEG_SE_CYL&0x003F);
                printf("%10li ",partition[i].pnSTARTSEC);
                printf("%10li ",partition[i].pnSIZE);
		t[i] = partition[i].pnSIZE/(2*1024);
		sectors = sectors + partition[i].pnSIZE;
                printf("\n\r");
               }
       /*
       for(j=0; j<4; j++) printf(" %d) %li MO  ",j+1,t[j]);
       tally = (sectors)/(2*1024);
       printf("\n\r\n\r%li MO (%li GO)",tally,tally/1024);
       */
       }

#endif
