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