1 ///////////////////////////////////////////////////////////////////////// 2 // $Id: hdimage.h 14181 2021-03-11 21:46:25Z vruppert $ 3 ///////////////////////////////////////////////////////////////////////// 4 // 5 // Copyright (C) 2005-2021 The Bochs Project 6 // 7 // This library is free software; you can redistribute it and/or 8 // modify it under the terms of the GNU Lesser General Public 9 // License as published by the Free Software Foundation; either 10 // version 2 of the License, or (at your option) any later version. 11 // 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 // Lesser General Public License for more details. 16 // 17 // You should have received a copy of the GNU Lesser General Public 18 // License along with this library; if not, write to the Free Software 19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 21 #ifndef BX_HDIMAGE_H 22 #define BX_HDIMAGE_H 23 24 // required for access() checks 25 #ifndef F_OK 26 #define F_OK 0 27 #endif 28 29 // hdimage capabilities 30 #define HDIMAGE_READONLY 1 31 #define HDIMAGE_HAS_GEOMETRY 2 32 #define HDIMAGE_AUTO_GEOMETRY 4 33 34 // hdimage format check return values 35 #define HDIMAGE_FORMAT_OK 0 36 #define HDIMAGE_SIZE_ERROR -1 37 #define HDIMAGE_READ_ERROR -2 38 #define HDIMAGE_NO_SIGNATURE -3 39 #define HDIMAGE_TYPE_ERROR -4 40 #define HDIMAGE_VERSION_ERROR -5 41 42 // SPARSE IMAGES HEADER 43 #define SPARSE_HEADER_MAGIC (0x02468ace) 44 #define SPARSE_HEADER_VERSION 2 45 #define SPARSE_HEADER_V1 1 46 #define SPARSE_HEADER_SIZE (256) // Plenty of room for later 47 #define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff) 48 49 typedef struct 50 { 51 Bit32u magic; 52 Bit32u version; 53 Bit32u pagesize; 54 Bit32u numpages; 55 Bit64u disk; 56 57 Bit32u padding[58]; 58 } sparse_header_t; 59 60 #define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image" 61 #define STANDARD_HEADER_V1 (0x00010000) 62 #define STANDARD_HEADER_VERSION (0x00020000) 63 #define STANDARD_HEADER_SIZE (512) 64 65 66 // WARNING : headers are kept in x86 (little) endianness 67 typedef struct 68 { 69 Bit8u magic[32]; 70 Bit8u type[16]; 71 Bit8u subtype[16]; 72 Bit32u version; 73 Bit32u header; 74 } standard_header_t; 75 76 #define REDOLOG_TYPE "Redolog" 77 #define REDOLOG_SUBTYPE_UNDOABLE "Undoable" 78 #define REDOLOG_SUBTYPE_VOLATILE "Volatile" 79 #define REDOLOG_SUBTYPE_GROWING "Growing" 80 81 #define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff) 82 83 #define UNDOABLE_REDOLOG_EXTENSION ".redolog" 84 #define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION)) 85 #define VOLATILE_REDOLOG_EXTENSION ".XXXXXX" 86 #define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION)) 87 88 typedef struct 89 { 90 // the fields in the header are kept in little endian 91 Bit32u catalog; // #entries in the catalog 92 Bit32u bitmap; // bitmap size in bytes 93 Bit32u extent; // extent size in bytes 94 Bit32u timestamp; // modification time in FAT format (subtype 'undoable' only) 95 Bit64u disk; // disk size in bytes 96 } redolog_specific_header_t; 97 98 typedef struct 99 { 100 // the fields in the header are kept in little endian 101 Bit32u catalog; // #entries in the catalog 102 Bit32u bitmap; // bitmap size in bytes 103 Bit32u extent; // extent size in bytes 104 Bit64u disk; // disk size in bytes 105 } redolog_specific_header_v1_t; 106 107 typedef struct 108 { 109 standard_header_t standard; 110 redolog_specific_header_t specific; 111 112 Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))]; 113 } redolog_header_t; 114 115 typedef struct 116 { 117 standard_header_t standard; 118 redolog_specific_header_v1_t specific; 119 120 Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_v1_t))]; 121 } redolog_header_v1_t; 122 123 // htod : convert host to disk (little) endianness 124 // dtoh : convert disk (little) to host endianness 125 #if defined (BX_LITTLE_ENDIAN) 126 #define htod16(val) (val) 127 #define dtoh16(val) (val) 128 #define htod32(val) (val) 129 #define dtoh32(val) (val) 130 #define htod64(val) (val) 131 #define dtoh64(val) (val) 132 #else 133 #define htod16(val) ((((val)&0xff00)>>8) | (((val)&0xff)<<8)) 134 #define dtoh16(val) htod16(val) 135 #define htod32(val) bx_bswap32(val) 136 #define dtoh32(val) htod32(val) 137 #define htod64(val) bx_bswap64(val) 138 #define dtoh64(val) htod64(val) 139 #endif 140 141 class device_image_t; 142 class redolog_t; 143 class cdrom_base_c; 144 145 #ifdef BXIMAGE 146 int bx_create_image_file(const char *filename); 147 #endif 148 BOCHSAPI_MSVCONLY int bx_read_image(int fd, Bit64s offset, void *buf, int count); 149 BOCHSAPI_MSVCONLY int bx_write_image(int fd, Bit64s offset, void *buf, int count); 150 BOCHSAPI_MSVCONLY int bx_close_image(int fd, const char *pathname); 151 #ifndef WIN32 152 int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, time_t *mtime); 153 #else 154 BOCHSAPI_MSVCONLY int hdimage_open_file(const char *pathname, int flags, Bit64u *fsize, FILETIME *mtime); 155 #endif 156 bool hdimage_detect_image_mode(const char *pathname, const char **image_mode); 157 BOCHSAPI_MSVCONLY bool hdimage_backup_file(int fd, const char *backup_fname); 158 BOCHSAPI_MSVCONLY bool hdimage_copy_file(const char *src, const char *dst); 159 bool coherency_check(device_image_t *ro_disk, redolog_t *redolog); 160 #ifndef WIN32 161 Bit16u fat_datetime(time_t time, int return_time); 162 #else 163 Bit16u BOCHSAPI_MSVCONLY fat_datetime(FILETIME time, int return_time); 164 #endif 165 166 // base class 167 class BOCHSAPI_MSVCONLY device_image_t 168 { 169 public: 170 // Default constructor 171 device_image_t(); ~device_image_t()172 virtual ~device_image_t() {} 173 174 // Open a image. Returns non-negative if successful. 175 virtual int open(const char* pathname); 176 177 // Open an image with specific flags. Returns non-negative if successful. 178 virtual int open(const char* pathname, int flags) = 0; 179 180 // Close the image. 181 virtual void close() = 0; 182 183 // Position ourselves. Return the resulting offset from the 184 // beginning of the file. 185 virtual Bit64s lseek(Bit64s offset, int whence) = 0; 186 187 // Read count bytes to the buffer buf. Return the number of 188 // bytes read (count). 189 virtual ssize_t read(void* buf, size_t count) = 0; 190 191 // Write count bytes from buf. Return the number of bytes 192 // written (count). 193 virtual ssize_t write(const void* buf, size_t count) = 0; 194 195 // Get image capabilities 196 virtual Bit32u get_capabilities(); 197 198 // Get modification time in FAT format 199 virtual Bit32u get_timestamp(); 200 201 // Check image format check_format(int fd,Bit64u imgsize)202 static int check_format(int fd, Bit64u imgsize) {return HDIMAGE_NO_SIGNATURE;} 203 204 #ifdef BXIMAGE 205 // Create new image file create_image(const char * pathname,Bit64u size)206 virtual int create_image(const char *pathname, Bit64u size) {return 0;} 207 #else 208 // Save/restore support 209 virtual void register_state(bx_list_c *parent); save_state(const char * backup_fname)210 virtual bool save_state(const char *backup_fname) {return 0;} restore_state(const char * backup_fname)211 virtual void restore_state(const char *backup_fname) {} 212 #endif 213 214 unsigned cylinders; 215 unsigned heads; 216 unsigned spt; 217 unsigned sect_size; 218 Bit64u hd_size; 219 protected: 220 #ifndef WIN32 221 time_t mtime; 222 #else 223 FILETIME mtime; 224 #endif 225 }; 226 227 // FLAT MODE 228 class flat_image_t : public device_image_t 229 { 230 public: 231 // Open an image with specific flags. Returns non-negative if successful. 232 int open(const char* pathname, int flags); 233 234 // Close the image. 235 void close(); 236 237 // Position ourselves. Return the resulting offset from the 238 // beginning of the file. 239 Bit64s lseek(Bit64s offset, int whence); 240 241 // Read count bytes to the buffer buf. Return the number of 242 // bytes read (count). 243 ssize_t read(void* buf, size_t count); 244 245 // Write count bytes from buf. Return the number of bytes 246 // written (count). 247 ssize_t write(const void* buf, size_t count); 248 249 // Check image format 250 static int check_format(int fd, Bit64u imgsize); 251 252 #ifndef BXIMAGE 253 // Save/restore support 254 bool save_state(const char *backup_fname); 255 void restore_state(const char *backup_fname); 256 #endif 257 258 private: 259 int fd; 260 const char *pathname; 261 }; 262 263 // CONCAT MODE 264 class concat_image_t : public device_image_t 265 { 266 public: 267 // Default constructor 268 concat_image_t(); 269 270 // Open an image with specific flags. Returns non-negative if successful. 271 int open(const char* pathname, int flags); 272 273 // Close the image. 274 void close(); 275 276 // Position ourselves. Return the resulting offset from the 277 // beginning of the file. 278 Bit64s lseek(Bit64s offset, int whence); 279 280 // Read count bytes to the buffer buf. Return the number of 281 // bytes read (count). 282 ssize_t read(void* buf, size_t count); 283 284 // Write count bytes from buf. Return the number of bytes 285 // written (count). 286 ssize_t write(const void* buf, size_t count); 287 288 #ifndef BXIMAGE 289 // Save/restore support 290 bool save_state(const char *backup_fname); 291 void restore_state(const char *backup_fname); 292 #endif 293 294 private: 295 #define BX_CONCAT_MAX_IMAGES 8 296 int fd_table[BX_CONCAT_MAX_IMAGES]; 297 Bit64u start_offset_table[BX_CONCAT_MAX_IMAGES]; 298 Bit64u length_table[BX_CONCAT_MAX_IMAGES]; 299 void increment_string(char *str); 300 int maxfd; // number of entries in tables that are valid 301 302 // notice if anyone does sequential read or write without seek in between. 303 // This can be supported pretty easily, but needs additional checks. 304 // 0=something other than seek was last operation 305 // 1=seek was last operation 306 //int seek_was_last_op; 307 308 // the following variables tell which partial image file to use for 309 // the next read and write. 310 int index; // index into table 311 int curr_fd; // fd to use for reads and writes 312 Bit64u curr_min, curr_max; // byte offset boundary of this image 313 Bit64u total_offset; // current byte offset 314 const char *pathname0; 315 }; 316 317 // SPARSE MODE 318 class sparse_image_t : public device_image_t 319 { 320 321 // Format of a sparse file: 322 // 256 byte header, containing details such as page size and number of pages 323 // Page indirection table, mapping virtual pages to physical pages within file 324 // Physical pages till end of file 325 326 public: 327 // Default constructor 328 sparse_image_t(); 329 330 // Open an image with specific flags. Returns non-negative if successful. 331 int open(const char* pathname, int flags); 332 333 // Close the image. 334 void close(); 335 336 // Position ourselves. Return the resulting offset from the 337 // beginning of the file. 338 Bit64s lseek(Bit64s offset, int whence); 339 340 // Read count bytes to the buffer buf. Return the number of 341 // bytes read (count). 342 ssize_t read(void* buf, size_t count); 343 344 // Write count bytes from buf. Return the number of bytes 345 // written (count). 346 ssize_t write(const void* buf, size_t count); 347 348 // Check image format 349 static int check_format(int fd, Bit64u imgsize); 350 351 #ifdef BXIMAGE 352 // Create new image file 353 int create_image(const char *pathname, Bit64u size); 354 #else 355 // Save/restore support 356 bool save_state(const char *backup_fname); 357 void restore_state(const char *backup_fname); 358 #endif 359 360 private: 361 int fd; 362 363 #ifdef _POSIX_MAPPED_FILES 364 void * mmap_header; 365 size_t mmap_length; 366 size_t system_pagesize_mask; 367 #endif 368 Bit32u *pagetable; 369 370 // Header is written to disk in little-endian (x86) format 371 // Thus needs to be converted on big-endian systems before read 372 // The pagetable is also kept little endian 373 374 sparse_header_t header; 375 376 Bit32u pagesize; 377 int pagesize_shift; 378 Bit32u pagesize_mask; 379 380 Bit64s data_start; 381 Bit64u underlying_filesize; 382 383 char *pathname; 384 385 //Bit64s position; 386 387 Bit32u position_virtual_page; 388 Bit32u position_physical_page; 389 Bit32u position_page_offset; 390 391 Bit64s underlying_current_filepos; 392 393 Bit64s total_size; 394 395 void panic(const char * message); 396 Bit64s get_physical_offset(); 397 void set_virtual_page(Bit32u new_virtual_page); 398 int read_header(); 399 ssize_t read_page_fragment(Bit32u read_virtual_page, Bit32u read_page_offset, size_t read_size, void * buf); 400 401 sparse_image_t *parent_image; 402 }; 403 404 #ifdef WIN32 405 class dll_image_t : public device_image_t 406 { 407 public: 408 dll_image_t(); 409 410 // Open an image with specific flags. Returns non-negative if successful. 411 int open(const char* pathname, int flags); 412 413 // Close the image. 414 void close(); 415 416 // Position ourselves. Return the resulting offset from the 417 // beginning of the file. 418 Bit64s lseek(Bit64s offset, int whence); 419 420 // Read count bytes to the buffer buf. Return the number of 421 // bytes read (count). 422 ssize_t read(void* buf, size_t count); 423 424 // Write count bytes from buf. Return the number of bytes 425 // written (count). 426 ssize_t write(const void* buf, size_t count); 427 428 private: 429 int vunit; 430 Bit64s vblk; 431 }; 432 #endif 433 434 // REDOLOG class 435 class BOCHSAPI_MSVCONLY redolog_t 436 { 437 public: 438 redolog_t(); 439 int make_header(const char* type, Bit64u size); 440 int create(const char* filename, const char* type, Bit64u size); 441 int create(int filedes, const char* type, Bit64u size); 442 int open(const char* filename, const char* type); 443 int open(const char* filename, const char* type, int flags); 444 void close(); 445 Bit64u get_size(); 446 Bit32u get_timestamp(); 447 bool set_timestamp(Bit32u timestamp); 448 449 Bit64s lseek(Bit64s offset, int whence); 450 ssize_t read(void* buf, size_t count); 451 ssize_t write(const void* buf, size_t count); 452 453 static int check_format(int fd, const char *subtype); 454 455 #ifdef BXIMAGE 456 int commit(device_image_t *base_image); 457 #else 458 bool save_state(const char *backup_fname); 459 #endif 460 461 private: 462 void print_header(); 463 char *pathname; 464 int fd; 465 redolog_header_t header; // Header is kept in x86 (little) endianness 466 Bit32u *catalog; 467 Bit8u *bitmap; 468 bool bitmap_update; 469 Bit32u extent_index; 470 Bit32u extent_offset; 471 Bit32u extent_next; 472 473 Bit32u bitmap_blocks; 474 Bit32u extent_blocks; 475 476 Bit64s imagepos; 477 }; 478 479 // GROWING MODE 480 class growing_image_t : public device_image_t 481 { 482 public: 483 // Contructor 484 growing_image_t(); 485 virtual ~growing_image_t(); 486 487 // Open an image with specific flags. Returns non-negative if successful. 488 int open(const char* pathname, int flags); 489 490 // Close the image. 491 void close(); 492 493 // Position ourselves. Return the resulting offset from the 494 // beginning of the file. 495 Bit64s lseek(Bit64s offset, int whence); 496 497 // Read count bytes to the buffer buf. Return the number of 498 // bytes read (count). 499 ssize_t read(void* buf, size_t count); 500 501 // Write count bytes from buf. Return the number of bytes 502 // written (count). 503 ssize_t write(const void* buf, size_t count); 504 505 // Get modification time in FAT format 506 virtual Bit32u get_timestamp(); 507 508 // Check image format 509 static int check_format(int fd, Bit64u imgsize); 510 511 #ifdef BXIMAGE 512 // Create new image file 513 int create_image(const char *pathname, Bit64u size); 514 #else 515 // Save/restore support 516 bool save_state(const char *backup_fname); 517 void restore_state(const char *backup_fname); 518 #endif 519 520 private: 521 redolog_t *redolog; 522 const char *pathname; 523 }; 524 525 // UNDOABLE MODE 526 class undoable_image_t : public device_image_t 527 { 528 public: 529 // Contructor 530 undoable_image_t(const char* redolog_name); 531 virtual ~undoable_image_t(); 532 533 // Open an image with specific flags. Returns non-negative if successful. 534 int open(const char* pathname, int flags); 535 536 // Close the image. 537 void close(); 538 539 // Position ourselves. Return the resulting offset from the 540 // beginning of the file. 541 Bit64s lseek(Bit64s offset, int whence); 542 543 // Read count bytes to the buffer buf. Return the number of 544 // bytes read (count). 545 ssize_t read(void* buf, size_t count); 546 547 // Write count bytes from buf. Return the number of bytes 548 // written (count). 549 ssize_t write(const void* buf, size_t count); 550 551 // Get image capabilities get_capabilities()552 virtual Bit32u get_capabilities() {return caps;} 553 554 #ifndef BXIMAGE 555 // Save/restore support 556 bool save_state(const char *backup_fname); 557 void restore_state(const char *backup_fname); 558 #endif 559 560 private: 561 redolog_t *redolog; // Redolog instance 562 device_image_t *ro_disk; // Read-only base disk instance 563 char *redolog_name; // Redolog name 564 Bit32u caps; 565 }; 566 567 568 // VOLATILE MODE 569 class volatile_image_t : public device_image_t 570 { 571 public: 572 // Contructor 573 volatile_image_t(const char* redolog_name); 574 virtual ~volatile_image_t(); 575 576 // Open an image with specific flags. Returns non-negative if successful. 577 int open(const char* pathname, int flags); 578 579 // Close the image. 580 void close(); 581 582 // Position ourselves. Return the resulting offset from the 583 // beginning of the file. 584 Bit64s lseek(Bit64s offset, int whence); 585 586 // Read count bytes to the buffer buf. Return the number of 587 // bytes read (count). 588 ssize_t read(void* buf, size_t count); 589 590 // Write count bytes from buf. Return the number of bytes 591 // written (count). 592 ssize_t write(const void* buf, size_t count); 593 594 // Get image capabilities get_capabilities()595 virtual Bit32u get_capabilities() {return caps;} 596 597 #ifndef BXIMAGE 598 // Save/restore support 599 bool save_state(const char *backup_fname); 600 void restore_state(const char *backup_fname); 601 #endif 602 603 private: 604 redolog_t *redolog; // Redolog instance 605 device_image_t *ro_disk; // Read-only base disk instance 606 char *redolog_name; // Redolog name 607 char *redolog_temp; // Redolog temporary file name 608 Bit32u caps; 609 }; 610 611 612 #ifndef BXIMAGE 613 614 #define DEV_hdimage_init_image(a,b,c) bx_hdimage_ctl.init_image(a,b,c) 615 #define DEV_hdimage_init_cdrom(a) bx_hdimage_ctl.init_cdrom(a) 616 617 class BOCHSAPI bx_hdimage_ctl_c : public logfunctions { 618 public: 619 bx_hdimage_ctl_c(); ~bx_hdimage_ctl_c()620 virtual ~bx_hdimage_ctl_c() {} 621 void init(void); 622 const char **get_mode_names(); 623 int get_mode_id(const char *mode); 624 void list_modules(void); 625 void exit(void); 626 device_image_t *init_image(const char *image_mode, Bit64u disk_size, const char *journal); 627 cdrom_base_c *init_cdrom(const char *dev); 628 }; 629 630 BOCHSAPI extern bx_hdimage_ctl_c bx_hdimage_ctl; 631 632 #endif // ifndef BXIMAGE 633 634 // 635 // The hdimage_locator class is used by device_image_t classes to register 636 // their name. The common hdimage code uses the static 'create' method 637 // to locate and instantiate a device_image_t class. 638 // 639 class BOCHSAPI_MSVCONLY hdimage_locator_c { 640 public: 641 static bool module_present(const char *mode); 642 static void cleanup(void); 643 static device_image_t *create(const char *mode, Bit64u disk_size, const char *journal); 644 static bool detect_image_mode(int fd, Bit64u disk_size, const char **image_mode); 645 protected: 646 hdimage_locator_c(const char *mode); 647 virtual ~hdimage_locator_c(); 648 virtual device_image_t *allocate(Bit64u disk_size, const char *journal) = 0; check_format(int fd,Bit64u disk_size)649 virtual int check_format(int fd, Bit64u disk_size) {return -1;} 650 private: 651 static hdimage_locator_c *all; 652 hdimage_locator_c *next; 653 const char *mode; 654 }; 655 656 #endif 657