Browse Source

Add Mac sanity checks

The main purpose of this code is to emit warnings when Mac quirks are
turned on and the image(s) are disks.

The warnings are emitted if any of the following checks fail:
    - The disk image contain Apple Magic signature
    - The HFS block size is correct
    - The Mac SCSI driver is smaller than or equal to the max size
    - The MAC SCSI driver is smaller than or equal to the image size
    - The Lido driver is not installed

The original implementation put the sanity checks under platform code.
Since none of the code is platform specific, it has been moved
to the root src directory so all build targets can take advantage
of the sanity checks.

Initial code authored by Eric Helgeson and taken from:
https://github.com/BlueSCSI/BlueSCSI-v2/commit/cc1ff5f4d03ce976d01ead09cee1106ce0acae08
https://github.com/BlueSCSI/BlueSCSI-v2/commit/d00ebe016b8c7ef4777c31cef9cd002043de7d46

Co-authored-by:  Eric Helgeson <erichelgeson@gmail.com>
Morio 2 năm trước cách đây
mục cha
commit
8677a96aa0
6 tập tin đã thay đổi với 193 bổ sung4 xóa
  1. 8 2
      src/ImageBackingStore.cpp
  2. 25 0
      src/ImageBackingStore.h
  3. 120 0
      src/QuirksCheck.cpp
  4. 35 0
      src/QuirksCheck.h
  5. 4 2
      src/ZuluSCSI_disk.cpp
  6. 1 0
      zuluscsi.ini

+ 8 - 2
src/ImageBackingStore.cpp

@@ -1,8 +1,8 @@
 /**
- * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
+ * Portions - Copyright (C) 2023 Eric Helgeson
+ * ZuluSCSI™ - Copyright (c) 2022-2023 Rabbit Hole Computing™
  *
  * This file is licensed under the GPL version 3 or any later version. 
- * It is derived from disk.c in SCSI2SD V6
  *
  * https://www.gnu.org/licenses/gpl-3.0.html
  * ----
@@ -145,6 +145,12 @@ bool ImageBackingStore::isRom()
     return m_isrom;
 }
 
+
+bool ImageBackingStore::isRaw()
+{
+    return m_israw;
+}
+
 bool ImageBackingStore::close()
 {
     if (m_israw)

+ 25 - 0
src/ImageBackingStore.h

@@ -1,3 +1,25 @@
+/**
+ * Portions - Copyright (C) 2023 Eric Helgeson
+ * ZuluSCSI™ - Copyright (c) 2022-2023 Rabbit Hole Computing™
+ *
+ * This file is licensed under the GPL version 3 or any later version. 
+ *
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ----
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+
 /* Access layer to image files associated with a SCSI device.
  * Currently supported image storage modes:
  *
@@ -49,6 +71,9 @@ public:
     // Is this internal ROM drive in microcontroller flash?
     bool isRom();
 
+    // Is this backed by raw passthrough
+    bool isRaw();
+
     // Close the image so that .isOpen() will return false.
     bool close();
 

+ 120 - 0
src/QuirksCheck.cpp

@@ -0,0 +1,120 @@
+/** 
+ * Copyright (C) 2023 Eric Helgeson
+ * Portions ZuluSCSI™ - Copyright (c) 2023 Rabbit Hole Computing™
+ * 
+ * This file is licensed under the GPL version 3 or any later version. 
+ * It is derived from BlueSCSI_platform_config_hook.cpp in BluSCSI-v2
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ---- 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+
+#include <minIni.h>
+#include "ZuluSCSI_disk.h"
+#include "ZuluSCSI_log.h"
+#include "QuirksCheck.h"
+#include <stdint.h>
+
+
+static bool isValidMacintoshImage(image_config_t *img)
+{
+    bool result = true;
+    const char apple_magic[2] = {0x45, 0x52};
+    const char block_size[2]  = {0x02, 0x00};  // 512 BE == 2
+    const char lido_sig[4] = {'C', 'M', 'S', '_' };
+    uint8_t tmp[4] = {0};
+
+    // Check for Apple Magic
+    img->file.seek(0);
+    img->file.read(tmp, 2);
+    if(memcmp(apple_magic, tmp, 2) != 0)
+    {
+        dbgmsg("---- Apple magic not found.");
+        result = false;
+    }
+    // Check HFS Block size is 512
+    img->file.seek(2);
+    img->file.read(tmp, 2);
+    if(memcmp(block_size, tmp, 2) != 0)
+    {
+        dbgmsg("---- Block size not 512", block_size);
+        result = false;
+    }
+    // Find SCSI Driver offset
+    img->file.seek(MACINTOSH_SCSI_DRIVER_OFFSET);
+    img->file.read(tmp, 4);
+    uint64_t driver_offset_blocks = int((unsigned char)(tmp[0]) << 24 | (unsigned char)(tmp[1]) << 16 |
+                                        (unsigned char)(tmp[2]) << 8  |  (unsigned char)(tmp[3]));
+    // Find size of SCSI Driver partition
+    img->file.seek(MACINTOSH_SCSI_DRIVER_SIZE_OFFSET);
+    img->file.read(tmp, 2);
+    int driver_size_blocks = int((unsigned char)(tmp[0]) << 8 | (unsigned char)(tmp[1]));
+    // SCSI Driver sanity checks
+    if((driver_size_blocks * MACINTOSH_BLOCK_SIZE) > MACINTOSH_SCSI_DRIVER_MAX_SIZE ||
+        (driver_offset_blocks * MACINTOSH_BLOCK_SIZE) > img->file.size())
+    {
+        dbgmsg("---- Invalid Macintosh SCSI Driver partition detected.");
+        result = false;
+    }
+    // Contains Lido Driver - driver causes issues on a Mac Plus and is generally slower than the Apple 4.3 or FWB.
+    // Also causes compatibility issues with other drivers.
+    img->file.seek(driver_offset_blocks * MACINTOSH_BLOCK_SIZE + LIDO_SIG_OFFSET);
+    img->file.read(tmp, 4);
+    if(memcmp(lido_sig, tmp, 4) == 0)
+    {
+        logmsg("---- WARNING: This drive contains the LIDO driver and may cause issues.");
+    }
+
+    return result;
+}
+
+// Called from ZuluSCSI_disk after image is initalized.
+static void macQuirksSanityCheck(image_config_t *img)
+{
+    if(ini_getbool("SCSI", "DisableMacSanityCheck", false, CONFIGFILE))
+    {
+        dbgmsg("---- Skipping Mac sanity check due to DisableMacSanityCheck");
+        return;
+    }
+    if(img->file.isRom() || img->file.isRaw())
+    {
+        dbgmsg("---- Skipping Mac sanity check on ROM/Raw Drive.");
+        return;
+    }
+    if (img->quirks == S2S_CFG_QUIRKS_APPLE)
+    {
+        if(img->deviceType == S2S_CFG_FIXED)
+        {
+            if(!isValidMacintoshImage(img))
+            {
+                logmsg("---- WARNING: This image does not appear to be a valid Macintosh disk image.");
+            }
+            else
+            {
+                dbgmsg("---- Valid Macintosh disk image detected.");
+            }
+        }
+        // Macintosh hosts reserve ID 7, so warn the user this configuration wont work
+        if((img->scsiId & S2S_CFG_TARGET_ID_BITS) == 7)
+        {
+          logmsg("---- WARNING: Quirks set to Apple so can not use SCSI ID 7!");
+        }
+    }
+}
+
+void quirksCheck(image_config_t *img)
+{
+    macQuirksSanityCheck(img);
+}

+ 35 - 0
src/QuirksCheck.h

@@ -0,0 +1,35 @@
+
+/** 
+ * Copyright (C) 2023 Eric Helgeson
+ * Portions ZuluSCSI™ - Copyright (c) 2023 Rabbit Hole Computing™
+ * 
+ * This file is licensed under the GPL version 3 or any later version. 
+ * It is derived from BlueSCSI_platform_config_hook.h in BluSCSI-v2
+ * 
+ * https://www.gnu.org/licenses/gpl-3.0.html
+ * ---- 
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
+**/
+
+#pragma once
+#include "ZuluSCSI_disk.h"
+
+void quirksCheck(image_config_t *img);
+
+// Macintosh Device image constants
+#define MACINTOSH_SCSI_DRIVER_OFFSET 18
+#define MACINTOSH_SCSI_DRIVER_SIZE_OFFSET MACINTOSH_SCSI_DRIVER_OFFSET + 4
+#define MACINTOSH_BLOCK_SIZE 512
+#define MACINTOSH_SCSI_DRIVER_MAX_SIZE 64 * MACINTOSH_BLOCK_SIZE // 32768
+#define LIDO_SIG_OFFSET 24

+ 4 - 2
src/ZuluSCSI_disk.cpp

@@ -37,6 +37,7 @@
 #include "ZuluSCSI_cdrom.h"
 #include "ImageBackingStore.h"
 #include "ROMDrive.h"
+#include "QuirksCheck.h"
 #include <minIni.h>
 #include <string.h>
 #include <strings.h>
@@ -432,6 +433,7 @@ bool scsiDiskOpenHDDImage(int target_idx, const char *filename, int scsi_id, int
 #ifdef PLATFORM_CONFIG_HOOK
         PLATFORM_CONFIG_HOOK(&img);
 #endif
+        quirksCheck(&img);
 
         if (img.name_from_image) 
         { 
@@ -669,7 +671,7 @@ static int findNextImageAfter(image_config_t &img,
     FsFile dir;
     if (dirname[0] == '\0')
     {
-        logmsg("Image directory name invalid for ID", (img.scsiId & 7));
+        logmsg("Image directory name invalid for ID", (img.scsiId & S2S_CFG_TARGET_ID_BITS));
         return 0;
     }
     if (!dir.open(dirname))
@@ -749,7 +751,7 @@ static int findNextImageAfter(image_config_t &img,
 
 int scsiDiskGetNextImageName(image_config_t &img, char *buf, size_t buflen)
 {
-    int target_idx = img.scsiId & 7;
+    int target_idx = img.scsiId & S2S_CFG_TARGET_ID_BITS;
 
     char section[6] = "SCSI0";
     section[4] = '0' + target_idx;

+ 1 - 0
zuluscsi.ini

@@ -46,6 +46,7 @@
 #ReinsertAfterEject = 1 # Reinsert next CD image after eject, if multiple images configured.
 #EjectButton = 0 # Enable eject by button 1 or 2, or set 0 to disable
 #CDAVolume = 63 # Change CD Audio default volume. Maximum 255.
+#DisableMacSanityCheck = 0 # Disable sanity warnings for Mac disk drives. Default is 0 - enable checks
 
 # Settings can be overridden for individual devices.
 #[SCSI2]