DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
include/bios_disk.h
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 #ifndef DOSBOX_BIOS_DISK_H
00020 #define DOSBOX_BIOS_DISK_H
00021 
00022 #include <stdio.h>
00023 #ifndef DOSBOX_MEM_H
00024 #include "mem.h"
00025 #endif
00026 #ifndef DOSBOX_DOS_INC_H
00027 #include "dos_inc.h"
00028 #endif
00029 #ifndef DOSBOX_BIOS_H
00030 #include "bios.h"
00031 #endif
00032 
00033 /* The Section handling Bios Disk Access */
00034 #define BIOS_MAX_DISK 10
00035 
00036 #define MAX_SWAPPABLE_DISKS 20
00037 struct diskGeo {
00038         Bit32u ksize;  /* Size in kilobytes */
00039         Bit16u secttrack; /* Sectors per track */
00040         Bit16u headscyl;  /* Heads per cylinder */
00041         Bit16u cylcount;  /* Cylinders per side */
00042         Bit16u biosval;   /* Type to return from BIOS */
00043     Bit16u bytespersect; /* Bytes per sector */
00044         Bit16u rootentries;  /* Root directory entries */
00045         Bit8u sectcluster;   /* Sectors per cluster */
00046         Bit8u mediaid;       /* Media ID */
00047 };
00048 extern diskGeo DiskGeometryList[];
00049 
00050 extern const Bit8u freedos_mbr[];
00051 
00052 class imageDisk {
00053 public:
00054         enum IMAGE_TYPE {
00055                 ID_BASE=0,
00056                 ID_EL_TORITO_FLOPPY,
00057         ID_VFD,
00058                 ID_MEMORY,
00059                 ID_VHD,
00060         ID_D88,
00061         ID_NFD
00062         };
00063 
00064         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00065         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00066         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00067         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00068 
00069         virtual void Set_Reserved_Cylinders(Bitu resCyl);
00070         virtual Bit32u Get_Reserved_Cylinders();
00071         virtual void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
00072         virtual void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
00073         virtual Bit8u GetBiosType(void);
00074         virtual Bit32u getSectSize(void);
00075         imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00076         imageDisk(FILE* diskimg, const char* diskName, Bit32u cylinders, Bit32u heads, Bit32u sectors, Bit32u sector_size, bool hardDrive);
00077         virtual ~imageDisk() { if(diskimg != NULL) { fclose(diskimg); diskimg=NULL; } };
00078 
00079         IMAGE_TYPE class_id;
00080         std::string diskname;
00081         bool active;
00082         Bit32u sector_size;
00083         Bit32u heads, cylinders, sectors;
00084         bool hardDrive;
00085         Bit64u diskSizeK;
00086 
00087 protected:
00088         imageDisk(IMAGE_TYPE class_id);
00089         FILE *diskimg;
00090         Bit8u floppytype;
00091 
00092         Bit32u reserved_cylinders;
00093     Bit64u image_base;
00094         Bit64u image_length;
00095 
00096 private:
00097         volatile int refcount;
00098 
00099 public:
00100         int Addref() {
00101                 return ++refcount;
00102         }
00103         int Release() {
00104                 int ret = --refcount;
00105                 if (ret < 0) {
00106                         fprintf(stderr,"WARNING: imageDisk Release() changed refcount to %d\n",ret);
00107                         abort();
00108                 }
00109                 if (ret == 0) delete this;
00110                 return ret;
00111         }
00112 };
00113 
00114 class imageDiskD88 : public imageDisk {
00115 public:
00116         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00117         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00118         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00119         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00120 
00121         imageDiskD88(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00122         virtual ~imageDiskD88();
00123 
00124     unsigned char fd_type_major;
00125     unsigned char fd_type_minor;
00126 
00127     enum { /* major */
00128         DISKTYPE_2D                     = 0,
00129         DISKTYPE_2DD,
00130         DISKTYPE_2HD
00131     };
00132 
00133     struct vfdentry {
00134         uint8_t         track,head,sector;
00135         uint16_t        sector_size;
00136 
00137         uint32_t        data_offset;
00138         uint32_t        entry_offset; // offset of the 12-byte entry this came from (if nonzero)
00139 
00140         vfdentry() : track(0), head(0), sector(0), sector_size(0), data_offset(0), entry_offset(0) {
00141         }
00142 
00143         uint16_t getSectorSize(void) const {
00144             return sector_size;
00145         }
00146     };
00147 
00148     vfdentry *findSector(Bit8u head,Bit8u track,Bit8u sector/*TODO: physical head?*/,unsigned int req_sector_size=0);
00149 
00150     std::vector<vfdentry> dents;
00151 };
00152 
00153 class imageDiskNFD : public imageDisk {
00154 public:
00155         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00156         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00157         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00158         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00159 
00160         imageDiskNFD(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk, unsigned int rev);
00161         virtual ~imageDiskNFD();
00162 
00163     struct vfdentry {
00164         uint8_t         track,head,sector;
00165         uint16_t        sector_size;
00166 
00167         uint32_t        data_offset;
00168         uint32_t        entry_offset; // offset of the 12-byte entry this came from (if nonzero)
00169 
00170         vfdentry() : track(0), head(0), sector(0), sector_size(0), data_offset(0), entry_offset(0) {
00171         }
00172 
00173         uint16_t getSectorSize(void) const {
00174             return sector_size;
00175         }
00176     };
00177 
00178     vfdentry *findSector(Bit8u head,Bit8u track,Bit8u sector/*TODO: physical head?*/,unsigned int req_sector_size=0);
00179 
00180     std::vector<vfdentry> dents;
00181 };
00182 
00183 class imageDiskVFD : public imageDisk {
00184 public:
00185         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00186         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00187         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00188         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00189 
00190         imageDiskVFD(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00191         virtual ~imageDiskVFD();
00192 
00193     struct vfdentry {
00194         uint8_t         track,head,sector,sizebyte;
00195         uint8_t         fillbyte;
00196 
00197         uint32_t        data_offset;
00198         uint32_t        entry_offset; // offset of the 12-byte entry this came from (if nonzero)
00199 
00200         vfdentry() : track(0), head(0), sector(0), sizebyte(0), fillbyte(0xFF), data_offset(0), entry_offset(0) {
00201         }
00202 
00203         bool hasSectorData(void) const {
00204             return fillbyte == 0xFF && data_offset != 0xFFFFFFFFUL;
00205         }
00206 
00207         bool hasFill(void) const {
00208             return fillbyte != 0xFF || data_offset == 0xFFFFFFFFUL;
00209         }
00210 
00211         uint16_t getSectorSize(void) const {
00212             return 128 << sizebyte;
00213         }
00214     };
00215 
00216     vfdentry *findSector(Bit8u head,Bit8u track,Bit8u sector/*TODO: physical head?*/,unsigned int req_sector_size=0);
00217 
00218     std::vector<vfdentry> dents;
00219 };
00220 
00221 class imageDiskMemory : public imageDisk {
00222 public:
00223         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00224         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00225         virtual Bit8u GetBiosType(void);
00226         virtual void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
00227         // Parition and format the ramdrive
00228         virtual Bit8u Format();
00229 
00230         // Create a hard drive image of a specified size; automatically select c/h/s
00231         imageDiskMemory(Bit32u imgSizeK);
00232         // Create a hard drive image of a specified geometry
00233         imageDiskMemory(Bit16u cylinders, Bit16u heads, Bit16u sectors, Bit16u sectorSize);
00234         // Create a floppy image of a specified geometry
00235         imageDiskMemory(diskGeo floppyGeometry);
00236         // Create a copy-on-write memory image of an existing image
00237         imageDiskMemory(imageDisk* underlyingImage);
00238         virtual ~imageDiskMemory();
00239 
00240 private:
00241         void init(diskGeo diskParams, bool isHardDrive, imageDisk* underlyingImage);
00242         bool CalculateFAT(Bit32u partitionStartingSector, Bit32u partitionLength, bool isHardDrive, Bit32u rootEntries, Bit32u* rootSectors, Bit32u* sectorsPerCluster, bool* isFat16, Bit32u* fatSectors, Bit32u* reservedSectors);
00243 
00244         Bit8u * * ChunkMap;
00245         Bit32u sectors_per_chunk;
00246         Bit32u chunk_size;
00247         Bit32u total_chunks;
00248         Bit32u total_sectors;
00249         imageDisk* underlyingImage;
00250 
00251         diskGeo floppyInfo;
00252 };
00253 
00254 class imageDiskVHD : public imageDisk {
00255 public:
00256         enum ErrorCodes : int
00257         {
00258                 OPEN_SUCCESS = 0,
00259                 ERROR_OPENING = 1,
00260                 INVALID_DATA = 2,
00261                 UNSUPPORTED_TYPE = 3,
00262                 INVALID_MATCH = 4,
00263                 INVALID_DATE = 5,
00264                 PARENT_ERROR = 0x10,
00265                 ERROR_OPENING_PARENT = 0x11,
00266                 PARENT_INVALID_DATA = 0x12,
00267                 PARENT_UNSUPPORTED_TYPE = 0x13,
00268                 PARENT_INVALID_MATCH = 0x14,
00269                 PARENT_INVALID_DATE = 0x15
00270         };
00271         enum VHDTypes : Bit32u
00272         {
00273                 VHD_TYPE_NONE = 0,
00274                 VHD_TYPE_FIXED = 2,
00275                 VHD_TYPE_DYNAMIC = 3,
00276                 VHD_TYPE_DIFFERENCING = 4
00277         };
00278         VHDTypes vhdType;
00279         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00280         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00281         static ErrorCodes Open(const char* fileName, const bool readOnly, imageDisk** imageDisk);
00282         static VHDTypes GetVHDType(const char* fileName);
00283         virtual ~imageDiskVHD();
00284 
00285 private:
00286         struct Geometry {
00287                 Bit16u cylinders;
00288                 Bit8u heads;
00289                 Bit8u sectors;
00290         };
00291         struct VHDFooter {
00292                 char cookie[8];
00293                 Bit32u features;
00294                 Bit32u fileFormatVersion;
00295                 Bit64u dataOffset;
00296                 Bit32u timeStamp;
00297                 char creatorApp[4];
00298                 Bit32u creatorVersion;
00299                 Bit32u creatorHostOS;
00300                 Bit64u originalSize;
00301                 Bit64u currentSize;
00302                 Geometry geometry;
00303                 VHDTypes diskType;
00304                 Bit32u checksum;
00305                 char uniqueId[16];
00306                 char savedState;
00307                 char reserved[427];
00308 
00309                 void SwapByteOrder();
00310                 Bit32u CalculateChecksum();
00311                 bool IsValid();
00312         };
00313         struct ParentLocatorEntry {
00314                 Bit32u platformCode;
00315                 Bit32u platformDataSpace;
00316                 Bit32u platformDataLength;
00317                 Bit32u reserved;
00318                 Bit64u platformDataOffset;
00319         };
00320         struct DynamicHeader {
00321                 char cookie[8];
00322                 Bit64u dataOffset;
00323                 Bit64u tableOffset;
00324                 Bit32u headerVersion;
00325                 Bit32u maxTableEntries;
00326                 Bit32u blockSize;
00327                 Bit32u checksum;
00328                 Bit8u parentUniqueId[16];
00329                 Bit32u parentTimeStamp;
00330                 Bit32u reserved;
00331                 Bit16u parentUnicodeName[256];
00332                 ParentLocatorEntry parentLocatorEntry[8];
00333                 char reserved2[256];
00334 
00335                 void SwapByteOrder();
00336                 Bit32u CalculateChecksum();
00337                 bool IsValid();
00338         };
00339 
00340         imageDiskVHD() : imageDisk(ID_VHD), parentDisk(NULL), copiedFooter(false), currentBlock(0xFFFFFFFF), currentBlockAllocated(false), currentBlockDirtyMap(NULL) { }
00341         static ErrorCodes TryOpenParent(const char* childFileName, const ParentLocatorEntry &entry, Bit8u* data, const Bit32u dataLength, imageDisk** disk, const Bit8u* uniqueId);
00342         static ErrorCodes Open(const char* fileName, const bool readOnly, imageDisk** imageDisk, const Bit8u* matchUniqueId);
00343         virtual bool loadBlock(const Bit32u blockNumber);
00344         static bool convert_UTF16_for_fopen(std::string &string, const void* data, const Bit32u dataLength);
00345 
00346         imageDisk* parentDisk;// = 0;
00347         Bit64u footerPosition;
00348         VHDFooter footer;
00349         VHDFooter originalFooter;
00350         bool copiedFooter;// = false;
00351         DynamicHeader dynamicHeader;
00352         Bit32u sectorsPerBlock;
00353         Bit32u blockMapSectors;
00354         Bit32u blockMapSize;
00355         Bit32u currentBlock;// = 0xFFFFFFFF;
00356         bool currentBlockAllocated;// = false;
00357         Bit32u currentBlockSectorOffset;
00358         Bit8u* currentBlockDirtyMap;// = 0;
00359 };
00360 
00361 void updateDPT(void);
00362 void incrementFDD(void);
00363 
00364 //in order to attach to the virtual IDE controllers, the disk must be mounted
00365 //  in the BIOS first (the imageDiskList array), so the IDE controller can obtain
00366 //  a reference to the drive in the imageDiskList array
00367 #define MAX_HDD_IMAGES 4
00368 #define MAX_DISK_IMAGES 6 //MAX_HDD_IMAGES + 2
00369 
00370 extern bool imageDiskChange[MAX_DISK_IMAGES];
00371 extern imageDisk *imageDiskList[MAX_DISK_IMAGES];
00372 extern imageDisk *diskSwap[20];
00373 extern Bits swapPosition;
00374 extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
00375 extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
00376 extern DOS_DTA *imgDTA;
00377 
00378 void swapInDisks(void);
00379 void swapInNextDisk(void);
00380 bool getSwapRequest(void);
00381 imageDisk *GetINT13HardDrive(unsigned char drv);
00382 imageDisk *GetINT13FloppyDrive(unsigned char drv);
00383 
00384 #endif