DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
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         };
00062 
00063         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00064         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00065         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00066         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00067 
00068         virtual void Set_Reserved_Cylinders(Bitu resCyl);
00069         virtual Bit32u Get_Reserved_Cylinders();
00070         virtual void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
00071         virtual void Get_Geometry(Bit32u * getHeads, Bit32u *getCyl, Bit32u *getSect, Bit32u *getSectSize);
00072         virtual Bit8u GetBiosType(void);
00073         virtual Bit32u getSectSize(void);
00074         imageDisk(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00075         imageDisk(FILE* diskimg, const char* diskName, Bit32u cylinders, Bit32u heads, Bit32u sectors, Bit32u sector_size, bool hardDrive);
00076         virtual ~imageDisk() { if(diskimg != NULL) { fclose(diskimg); diskimg=NULL; } };
00077 
00078         IMAGE_TYPE class_id;
00079         std::string diskname;
00080         bool active;
00081         Bit32u sector_size;
00082         Bit32u heads, cylinders, sectors;
00083         bool hardDrive;
00084         Bit64u diskSizeK;
00085 
00086 protected:
00087         imageDisk(IMAGE_TYPE class_id);
00088         FILE *diskimg;
00089         Bit8u floppytype;
00090 
00091         Bit32u reserved_cylinders;
00092     Bit64u image_base;
00093         Bit64u image_length;
00094 
00095 private:
00096         volatile int refcount;
00097 
00098 public:
00099         int Addref() {
00100                 return ++refcount;
00101         }
00102         int Release() {
00103                 int ret = --refcount;
00104                 if (ret < 0) {
00105                         fprintf(stderr,"WARNING: imageDisk Release() changed refcount to %d\n",ret);
00106                         abort();
00107                 }
00108                 if (ret == 0) delete this;
00109                 return ret;
00110         }
00111 };
00112 
00113 class imageDiskD88 : public imageDisk {
00114 public:
00115         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00116         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00117         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00118         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00119 
00120         imageDiskD88(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00121         virtual ~imageDiskD88();
00122 
00123     unsigned char fd_type_major;
00124     unsigned char fd_type_minor;
00125 
00126     enum { /* major */
00127         DISKTYPE_2D                     = 0,
00128         DISKTYPE_2DD,
00129         DISKTYPE_2HD
00130     };
00131 
00132     struct vfdentry {
00133         uint8_t         track,head,sector;
00134         uint16_t        sector_size;
00135 
00136         uint32_t        data_offset;
00137         uint32_t        entry_offset; // offset of the 12-byte entry this came from (if nonzero)
00138 
00139         vfdentry() : track(0), head(0), sector(0), sector_size(0), data_offset(0), entry_offset(0) {
00140         }
00141 
00142         uint16_t getSectorSize(void) const {
00143             return sector_size;
00144         }
00145     };
00146 
00147     vfdentry *findSector(Bit8u head,Bit8u track,Bit8u sector/*TODO: physical head?*/,unsigned int req_sector_size=0);
00148 
00149     std::vector<vfdentry> dents;
00150 };
00151 
00152 class imageDiskVFD : public imageDisk {
00153 public:
00154         virtual Bit8u Read_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,void * data,unsigned int req_sector_size=0);
00155         virtual Bit8u Write_Sector(Bit32u head,Bit32u cylinder,Bit32u sector,const void * data,unsigned int req_sector_size=0);
00156         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00157         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00158 
00159         imageDiskVFD(FILE *imgFile, Bit8u *imgName, Bit32u imgSizeK, bool isHardDisk);
00160         virtual ~imageDiskVFD();
00161 
00162     struct vfdentry {
00163         uint8_t         track,head,sector,sizebyte;
00164         uint8_t         fillbyte;
00165 
00166         uint32_t        data_offset;
00167         uint32_t        entry_offset; // offset of the 12-byte entry this came from (if nonzero)
00168 
00169         vfdentry() : track(0), head(0), sector(0), sizebyte(0), fillbyte(0xFF), data_offset(0), entry_offset(0) {
00170         }
00171 
00172         bool hasSectorData(void) const {
00173             return fillbyte == 0xFF;
00174         }
00175 
00176         bool hasFill(void) const {
00177             return fillbyte != 0xFF;
00178         }
00179 
00180         uint16_t getSectorSize(void) const {
00181             return 128 << sizebyte;
00182         }
00183     };
00184 
00185     vfdentry *findSector(Bit8u head,Bit8u track,Bit8u sector/*TODO: physical head?*/,unsigned int req_sector_size=0);
00186 
00187     std::vector<vfdentry> dents;
00188 };
00189 
00190 class imageDiskMemory : public imageDisk {
00191 public:
00192         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00193         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00194         virtual Bit8u GetBiosType(void);
00195         virtual void Set_Geometry(Bit32u setHeads, Bit32u setCyl, Bit32u setSect, Bit32u setSectSize);
00196         // Parition and format the ramdrive
00197         virtual Bit8u Format();
00198 
00199         // Create a hard drive image of a specified size; automatically select c/h/s
00200         imageDiskMemory(Bit32u imgSizeK);
00201         // Create a hard drive image of a specified geometry
00202         imageDiskMemory(Bit16u cylinders, Bit16u heads, Bit16u sectors, Bit16u sectorSize);
00203         // Create a floppy image of a specified geometry
00204         imageDiskMemory(diskGeo floppyGeometry);
00205         // Create a copy-on-write memory image of an existing image
00206         imageDiskMemory(imageDisk* underlyingImage);
00207         virtual ~imageDiskMemory();
00208 
00209 private:
00210         void init(diskGeo diskParams, bool isHardDrive, imageDisk* underlyingImage);
00211         bool CalculateFAT(Bit32u partitionStartingSector, Bit32u partitionLength, bool isHardDrive, Bit32u rootEntries, Bit32u* rootSectors, Bit32u* sectorsPerCluster, bool* isFat16, Bit32u* fatSectors, Bit32u* reservedSectors);
00212 
00213         Bit8u * * ChunkMap;
00214         Bit32u sectors_per_chunk;
00215         Bit32u chunk_size;
00216         Bit32u total_chunks;
00217         Bit32u total_sectors;
00218         imageDisk* underlyingImage;
00219 
00220         diskGeo floppyInfo;
00221 };
00222 
00223 class imageDiskVHD : public imageDisk {
00224 public:
00225         enum ErrorCodes : int
00226         {
00227                 OPEN_SUCCESS = 0,
00228                 ERROR_OPENING = 1,
00229                 INVALID_DATA = 2,
00230                 UNSUPPORTED_TYPE = 3,
00231                 INVALID_MATCH = 4,
00232                 INVALID_DATE = 5,
00233                 PARENT_ERROR = 0x10,
00234                 ERROR_OPENING_PARENT = 0x11,
00235                 PARENT_INVALID_DATA = 0x12,
00236                 PARENT_UNSUPPORTED_TYPE = 0x13,
00237                 PARENT_INVALID_MATCH = 0x14,
00238                 PARENT_INVALID_DATE = 0x15
00239         };
00240         enum VHDTypes : Bit32u
00241         {
00242                 VHD_TYPE_NONE = 0,
00243                 VHD_TYPE_FIXED = 2,
00244                 VHD_TYPE_DYNAMIC = 3,
00245                 VHD_TYPE_DIFFERENCING = 4
00246         };
00247         VHDTypes vhdType;
00248         virtual Bit8u Read_AbsoluteSector(Bit32u sectnum, void * data);
00249         virtual Bit8u Write_AbsoluteSector(Bit32u sectnum, const void * data);
00250         static ErrorCodes Open(const char* fileName, const bool readOnly, imageDisk** imageDisk);
00251         static VHDTypes GetVHDType(const char* fileName);
00252         virtual ~imageDiskVHD();
00253 
00254 private:
00255         struct Geometry {
00256                 Bit16u cylinders;
00257                 Bit8u heads;
00258                 Bit8u sectors;
00259         };
00260         struct VHDFooter {
00261                 char cookie[8];
00262                 Bit32u features;
00263                 Bit32u fileFormatVersion;
00264                 Bit64u dataOffset;
00265                 Bit32u timeStamp;
00266                 char creatorApp[4];
00267                 Bit32u creatorVersion;
00268                 Bit32u creatorHostOS;
00269                 Bit64u originalSize;
00270                 Bit64u currentSize;
00271                 Geometry geometry;
00272                 VHDTypes diskType;
00273                 Bit32u checksum;
00274                 char uniqueId[16];
00275                 char savedState;
00276                 char reserved[427];
00277 
00278                 void SwapByteOrder();
00279                 Bit32u CalculateChecksum();
00280                 bool IsValid();
00281         };
00282         struct ParentLocatorEntry {
00283                 Bit32u platformCode;
00284                 Bit32u platformDataSpace;
00285                 Bit32u platformDataLength;
00286                 Bit32u reserved;
00287                 Bit64u platformDataOffset;
00288         };
00289         struct DynamicHeader {
00290                 char cookie[8];
00291                 Bit64u dataOffset;
00292                 Bit64u tableOffset;
00293                 Bit32u headerVersion;
00294                 Bit32u maxTableEntries;
00295                 Bit32u blockSize;
00296                 Bit32u checksum;
00297                 Bit8u parentUniqueId[16];
00298                 Bit32u parentTimeStamp;
00299                 Bit32u reserved;
00300                 Bit16u parentUnicodeName[256];
00301                 ParentLocatorEntry parentLocatorEntry[8];
00302                 char reserved2[256];
00303 
00304                 void SwapByteOrder();
00305                 Bit32u CalculateChecksum();
00306                 bool IsValid();
00307         };
00308 
00309         imageDiskVHD() : imageDisk(ID_VHD), parentDisk(NULL), copiedFooter(false), currentBlock(0xFFFFFFFF), currentBlockAllocated(false), currentBlockDirtyMap(NULL) { }
00310         static ErrorCodes TryOpenParent(const char* childFileName, const ParentLocatorEntry &entry, Bit8u* data, const Bit32u dataLength, imageDisk** disk, const Bit8u* uniqueId);
00311         static ErrorCodes Open(const char* fileName, const bool readOnly, imageDisk** imageDisk, const Bit8u* matchUniqueId);
00312         virtual bool loadBlock(const Bit32u blockNumber);
00313         static bool convert_UTF16_for_fopen(std::string &string, const void* data, const Bit32u dataLength);
00314 
00315         imageDisk* parentDisk;// = 0;
00316         Bit64u footerPosition;
00317         VHDFooter footer;
00318         VHDFooter originalFooter;
00319         bool copiedFooter;// = false;
00320         DynamicHeader dynamicHeader;
00321         Bit32u sectorsPerBlock;
00322         Bit32u blockMapSectors;
00323         Bit32u blockMapSize;
00324         Bit32u currentBlock;// = 0xFFFFFFFF;
00325         bool currentBlockAllocated;// = false;
00326         Bit32u currentBlockSectorOffset;
00327         Bit8u* currentBlockDirtyMap;// = 0;
00328 };
00329 
00330 void updateDPT(void);
00331 void incrementFDD(void);
00332 
00333 //in order to attach to the virtual IDE controllers, the disk must be mounted
00334 //  in the BIOS first (the imageDiskList array), so the IDE controller can obtain
00335 //  a reference to the drive in the imageDiskList array
00336 #define MAX_HDD_IMAGES 4
00337 #define MAX_DISK_IMAGES 6 //MAX_HDD_IMAGES + 2
00338 
00339 extern imageDisk *imageDiskList[MAX_DISK_IMAGES];
00340 extern imageDisk *diskSwap[20];
00341 extern Bits swapPosition;
00342 extern Bit16u imgDTASeg; /* Real memory location of temporary DTA pointer for fat image disk access */
00343 extern RealPt imgDTAPtr; /* Real memory location of temporary DTA pointer for fat image disk access */
00344 extern DOS_DTA *imgDTA;
00345 
00346 void swapInDisks(void);
00347 void swapInNextDisk(void);
00348 bool getSwapRequest(void);
00349 imageDisk *GetINT13HardDrive(unsigned char drv);
00350 imageDisk *GetINT13FloppyDrive(unsigned char drv);
00351 
00352 #endif