ROMDrive.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /**
  2. * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
  3. * Function romDriveClear() Copyright (c) 2023 Eric Helgeson
  4. *
  5. * This file is licensed under the GPL version 3 or any later version. 
  6. * It is derived from disk.c in SCSI2SD V6
  7. *
  8. * https://www.gnu.org/licenses/gpl-3.0.html
  9. * ----
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version. 
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18. * GNU General Public License for more details. 
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  22. **/
  23. #include "ROMDrive.h"
  24. #include <SdFat.h>
  25. #include <ZuluSCSI_platform.h>
  26. #include "ZuluSCSI_log.h"
  27. #include "ZuluSCSI_config.h"
  28. #include <strings.h>
  29. #include <string.h>
  30. extern "C" {
  31. #include <scsi.h>
  32. }
  33. extern SdFs SD;
  34. #ifndef PLATFORM_HAS_ROM_DRIVE
  35. bool romDriveCheckPresent(romdrive_hdr_t *hdr)
  36. {
  37. return false;
  38. }
  39. bool romDriveClear()
  40. {
  41. logmsg("---- Platform does not support ROM drive");
  42. return false;
  43. }
  44. bool scsiDiskProgramRomDrive(const char *filename, int scsi_id, int blocksize, S2S_CFG_TYPE type)
  45. {
  46. logmsg("---- Platform does not support ROM drive");
  47. return false;
  48. }
  49. bool romDriveRead(uint8_t *buf, uint32_t start, uint32_t count)
  50. {
  51. return false;
  52. }
  53. #else
  54. // Check if the romdrive is present
  55. bool romDriveCheckPresent(romdrive_hdr_t *hdr)
  56. {
  57. romdrive_hdr_t tmp;
  58. if (!hdr) hdr = &tmp;
  59. if (!platform_read_romdrive((uint8_t*)hdr, 0, sizeof(romdrive_hdr_t)))
  60. {
  61. return false;
  62. }
  63. if (memcmp(hdr->magic, "ROMDRIVE", 8) != 0)
  64. {
  65. return false;
  66. }
  67. if (hdr->imagesize <= 0 || hdr->scsi_id < 0 || hdr->scsi_id > 8)
  68. {
  69. return false;
  70. }
  71. return true;
  72. }
  73. // Clear the drive metadata header
  74. bool romDriveClear()
  75. {
  76. romdrive_hdr_t hdr = {0x0};
  77. if (!platform_write_romdrive((const uint8_t*)&hdr, 0, PLATFORM_ROMDRIVE_PAGE_SIZE))
  78. {
  79. logmsg("-- Failed to clear ROM drive");
  80. return false;
  81. }
  82. logmsg("-- Cleared ROM drive");
  83. SD.remove("CLEAR_ROM");
  84. return true;
  85. }
  86. // Load an image file to romdrive
  87. bool scsiDiskProgramRomDrive(const char *filename, int scsi_id, int blocksize, S2S_CFG_TYPE type)
  88. {
  89. FsFile file = SD.open(filename, O_RDONLY);
  90. if (!file.isOpen())
  91. {
  92. logmsg("---- Failed to open: ", filename);
  93. return false;
  94. }
  95. uint64_t filesize = file.size();
  96. uint32_t maxsize = platform_get_romdrive_maxsize() - PLATFORM_ROMDRIVE_PAGE_SIZE;
  97. logmsg("---- SCSI ID: ", scsi_id, " blocksize ", blocksize, " type ", (int)type);
  98. logmsg("---- ROM drive maximum size is ", (int)maxsize,
  99. " bytes, image file is ", (int)filesize, " bytes");
  100. if (filesize > maxsize)
  101. {
  102. logmsg("---- Image size exceeds ROM space, not loading");
  103. file.close();
  104. return false;
  105. }
  106. romdrive_hdr_t hdr = {};
  107. memcpy(hdr.magic, "ROMDRIVE", 8);
  108. hdr.scsi_id = scsi_id;
  109. hdr.imagesize = filesize;
  110. hdr.blocksize = blocksize;
  111. hdr.drivetype = type;
  112. // Program the drive metadata header
  113. if (!platform_write_romdrive((const uint8_t*)&hdr, 0, PLATFORM_ROMDRIVE_PAGE_SIZE))
  114. {
  115. logmsg("---- Failed to program ROM drive header");
  116. file.close();
  117. return false;
  118. }
  119. // Program the drive contents
  120. uint32_t pages = (filesize + PLATFORM_ROMDRIVE_PAGE_SIZE - 1) / PLATFORM_ROMDRIVE_PAGE_SIZE;
  121. for (uint32_t i = 0; i < pages; i++)
  122. {
  123. if (i % 2)
  124. LED_ON();
  125. else
  126. LED_OFF();
  127. if (file.read(scsiDev.data, PLATFORM_ROMDRIVE_PAGE_SIZE) <= 0 ||
  128. !platform_write_romdrive(scsiDev.data, (i + 1) * PLATFORM_ROMDRIVE_PAGE_SIZE, PLATFORM_ROMDRIVE_PAGE_SIZE))
  129. {
  130. logmsg("---- Failed to program ROM drive page ", (int)i);
  131. file.close();
  132. return false;
  133. }
  134. }
  135. LED_OFF();
  136. file.close();
  137. char newname[MAX_FILE_PATH * 2] = "";
  138. strlcat(newname, filename, sizeof(newname));
  139. strlcat(newname, "_loaded", sizeof(newname));
  140. SD.rename(filename, newname);
  141. logmsg("---- ROM drive programming successful, image file renamed to ", newname);
  142. return true;
  143. }
  144. bool romDriveRead(uint8_t *buf, uint32_t start, uint32_t count)
  145. {
  146. return platform_read_romdrive(buf, start + PLATFORM_ROMDRIVE_PAGE_SIZE, count);
  147. }
  148. #endif