Forráskód Böngészése

SdFat: Update to version with GPT support

Petteri Aimonen 2 éve
szülő
commit
747c4308e1

+ 5 - 15
lib/SdFat_NoArduino/src/ExFatLib/ExFatPartition.cpp

@@ -24,6 +24,7 @@
  */
 #define DBG_FILE "ExFatPartition.cpp"
 #include "../common/DebugMacros.h"
+#include "../common/PartitionTable.h"
 #include "ExFatLib.h"
 //------------------------------------------------------------------------------
 // return 0 if error, 1 if no space, else start cluster.
@@ -269,29 +270,18 @@ int32_t ExFatPartition::freeClusterCount() {
 bool ExFatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
   pbs_t* pbs;
   BpbExFat_t* bpb;
-  MbrSector_t* mbr;
   m_fatType = 0;
   m_blockDev = dev;
   cacheInit(m_blockDev);
   // if part == 0 assume super floppy with FAT boot sector in sector zero
-  // if part > 0 assume mbr volume with partition table
+  // if part > 0 read MBR / GPT partition table
   if (part) {
-    if (part > 4) {
-      DBG_FAIL_MACRO;
-      goto fail;
-    }
-    mbr = reinterpret_cast<MbrSector_t*>
-          (dataCachePrepare(0, FsCache::CACHE_FOR_READ));
-    if (!mbr) {
-      DBG_FAIL_MACRO;
-      goto fail;
-    }
-    MbrPart_t* mp = mbr->part + part - 1;
-    if (mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) {
+    volStart = partitionTableGetVolumeStartSector(m_dataCache, part);
+
+    if (!volStart) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    volStart = getLe32(mp->relativeSectors);
   }
   pbs = reinterpret_cast<pbs_t*>
         (dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));

+ 5 - 15
lib/SdFat_NoArduino/src/FatLib/FatPartition.cpp

@@ -25,6 +25,7 @@
 #include <string.h>
 #define DBG_FILE "FatPartition.cpp"
 #include "../common/DebugMacros.h"
+#include "../common/PartitionTable.h"
 #include "FatLib.h"
 //------------------------------------------------------------------------------
 bool FatPartition::allocateCluster(uint32_t current, uint32_t* next) {
@@ -396,7 +397,6 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
   m_blockDev = dev;
   pbs_t* pbs;
   BpbFat32_t* bpb;
-  MbrSector_t* mbr;
   uint8_t tmp;
   m_fatType = 0;
   m_allocSearchStart = 1;
@@ -405,24 +405,14 @@ bool FatPartition::init(FsBlockDevice* dev, uint8_t part, uint32_t volStart) {
   m_fatCache.init(dev);
 #endif  // USE_SEPARATE_FAT_CACHE
   // if part == 0 assume super floppy with FAT boot sector in sector zero
-  // if part > 0 assume mbr volume with partition table
+  // if part > 0 read MBR/GPT partition table
   if (part) {
-    if (part > 4) {
-      DBG_FAIL_MACRO;
-      goto fail;
-    }
-    mbr = reinterpret_cast<MbrSector_t*>
-          (dataCachePrepare(0, FsCache::CACHE_FOR_READ));
-    if (!mbr) {
-      DBG_FAIL_MACRO;
-      goto fail;
-    }
-    MbrPart_t* mp = mbr->part + part - 1;
-    if (mp->type == 0 || (mp->boot != 0 && mp->boot != 0X80)) {
+    volStart = partitionTableGetVolumeStartSector(m_cache, part);
+
+    if (!volStart) {
       DBG_FAIL_MACRO;
       goto fail;
     }
-    volStart = getLe32(mp->relativeSectors);
   }
   pbs = reinterpret_cast<pbs_t*>
         (dataCachePrepare(volStart, FsCache::CACHE_FOR_READ));

+ 30 - 0
lib/SdFat_NoArduino/src/common/FsStructs.h

@@ -132,6 +132,36 @@ typedef struct masterBootRecordSector {
   uint8_t   signature[2];
 } MbrSector_t;
 //------------------------------------------------------------------------------
+// GPT partition structures based on https://github.com/KirollousMoheb/GUID-Partition-Table-Parser
+// Copyright (c) 2022 Kirollous Moheb, under MIT License
+typedef struct
+{
+  uint8_t part_type_guid[16];
+  uint8_t unique_part_guid[16];
+  uint8_t first_lba[8];
+  uint8_t last_lba[8];
+  uint8_t attr_flags[8];
+  uint8_t part_name[72];
+} GPT_PartitionEntry_t;
+//------------------------------------------------------------------------------
+typedef struct
+{
+  uint8_t signature[8];
+  uint8_t revision[4];
+  uint8_t header_size[4];
+  uint8_t crc32[4];
+  uint8_t reserved[4];
+  uint8_t current_lba[8];
+  uint8_t backup_lba[8];
+  uint8_t first_usable_lba[8];
+  uint8_t last_usable_lba[8];
+  uint8_t disk_guid[16];
+  uint8_t part_entry_start_lba[8];
+  uint8_t num_part_entries[4];
+  uint8_t part_entry_size[4];
+  uint8_t crc32_part_array[4];
+} GPT_Header_t;
+//------------------------------------------------------------------------------
 typedef struct partitionBootSector {
   uint8_t  jmpInstruction[3];
   char     oemName[8];

+ 103 - 0
lib/SdFat_NoArduino/src/common/PartitionTable.cpp

@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2011-2022 Bill Greiman
+ * 
+ * This file is part of the SdFat library for SD memory cards.
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "PartitionTable.h"
+#include "DebugMacros.h"
+#include "FsStructs.h"
+
+// Read MBR format partition table, retrieve the start sector number of a volume
+static uint32_t partitionTableGetVolumeStartSectorMBR(FsCache& fscache, uint8_t part)
+{
+  if (part <= 0 || part > 4) {
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+
+  const uint8_t *sector = fscache.prepare(0, FsCache::CACHE_FOR_READ);
+  const MbrSector_t *mbr = reinterpret_cast<const MbrSector_t*>(sector);
+  if (!mbr) {
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+  
+  const MbrPart_t *mp = mbr->part + part - 1;
+  if (mp->type == 0 || getLe32(mp->totalSectors) == 0) {
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+
+  return getLe32(mp->relativeSectors);
+}
+
+// Read GPT format partition table, retrieve the start sector number of a volume
+static uint32_t partitionTableGetVolumeStartSectorGPT(FsCache& fscache, uint8_t part)
+{
+  if (part <= 0 || part > 4) {
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+
+  const uint8_t *sector = fscache.prepare(1, FsCache::CACHE_FOR_READ);
+  const GPT_Header_t *gpt = reinterpret_cast<const GPT_Header_t*>(sector);
+
+  if (getLe64(gpt->signature) != 0x5452415020494645ULL) {
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+
+  // First 4 partition table entries are in LBA 2
+  sector = fscache.prepare(2, FsCache::CACHE_FOR_READ);
+  const GPT_PartitionEntry_t *partentry =
+    reinterpret_cast<const GPT_PartitionEntry_t*>(sector + 128 * (part - 1));
+
+  uint64_t startSector = getLe64(partentry->first_lba);
+  uint32_t startSector32 = static_cast<uint32_t>(startSector);
+  if (startSector32 != startSector)
+  {
+    // Currently limited to 2^32 sectors = 2 TB by other parts of SdFat code.
+    DBG_FAIL_MACRO;
+    return 0;
+  }
+
+  return startSector32;
+}
+
+uint32_t partitionTableGetVolumeStartSector(FsCache& fscache, uint8_t part)
+{
+  uint32_t start;
+  
+  // Check for GPT partition table first, because it has clearly identifiable
+  // signature. It is also common for GPT-partitioned drives to have MBR-style
+  // fallback boot record at the start.
+  start = partitionTableGetVolumeStartSectorGPT(fscache, part);
+
+  if (start == 0)
+  {
+    start = partitionTableGetVolumeStartSectorMBR(fscache, part);
+  }
+
+  return start;
+}

+ 40 - 0
lib/SdFat_NoArduino/src/common/PartitionTable.h

@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2011-2022 Bill Greiman
+ * 
+ * This file is part of the SdFat library for SD memory cards.
+ *
+ * MIT License
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+#ifndef PartitionTable_h
+#define PartitionTable_h
+
+#include "FsCache.h"
+
+/**
+ * Parse either MBR or GPT format partition table to get the first sector
+ * number of a volume.
+ * \param[in] fscache Cache instance used to read the disk.
+ * \param[in] part Index of partition to read, 1 to 4.
+ * \return First sector of volume, or 0 if partition table could not be parsed.
+ */
+uint32_t partitionTableGetVolumeStartSector(FsCache& fscache, uint8_t part);
+
+#endif

+ 2 - 2
platformio.ini

@@ -16,7 +16,7 @@ build_flags =
     -DSCSI2SD_BUFFER_SIZE=4096
     -DUSE_ARDUINO=1
 lib_deps =
-    SdFat=https://github.com/greiman/SdFat#2.2.0
+    SdFat=https://github.com/rabbitholecomputing/SdFat#2.2.0-gpt
     minIni
     ZuluSCSI_platform_template
     SCSI2SD
@@ -71,7 +71,7 @@ extra_scripts = src/build_bootloader.py
 board_build.ldscript = lib/ZuluSCSI_platform_RP2040/rp2040.ld
 ldscript_bootloader = lib/ZuluSCSI_platform_RP2040/rp2040_btldr.ld
 lib_deps =
-    SdFat=https://github.com/greiman/SdFat#2.2.0
+    SdFat=https://github.com/rabbitholecomputing/SdFat#2.2.0-gpt
     minIni
     ZuluSCSI_platform_RP2040
     SCSI2SD