DOSBox-X
|
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