PARTITION* _FAT_partition_constructor (const DISC_INTERFACE* disc, uint32_t cacheSize, uint32_t sectorsPerPage, sec_t startSector) { PARTITION* partition; uint8_t sectorBuffer[BYTES_PER_READ] = {0}; // Read first sector of disc if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } // Make sure it is a valid MBR or boot sector if ( (sectorBuffer[BPB_bootSig_55] != 0x55) || (sectorBuffer[BPB_bootSig_AA] != 0xAA)) { return NULL; } if (startSector != 0) { // We're told where to start the partition, so just accept it } else if (!memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check if there is a FAT string, which indicates this is a boot sector startSector = 0; } else if (!memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { // Check for FAT32 startSector = 0; } else { startSector = FindFirstValidPartition(disc); if (!_FAT_disc_readSectors (disc, startSector, 1, sectorBuffer)) { return NULL; } } // Now verify that this is indeed a FAT partition if (memcmp(sectorBuffer + BPB_FAT16_fileSysType, FAT_SIG, sizeof(FAT_SIG)) && memcmp(sectorBuffer + BPB_FAT32_fileSysType, FAT_SIG, sizeof(FAT_SIG))) { return NULL; } // check again for the last two cases to make sure that we really have a FAT filesystem here // and won't corrupt any data if(memcmp(sectorBuffer + BPB_FAT16_fileSysType, "FAT", 3) != 0 && memcmp(sectorBuffer + BPB_FAT32_fileSysType, "FAT32", 5) != 0) { return NULL; } partition = (PARTITION*) _FAT_mem_allocate (sizeof(PARTITION)); if (partition == NULL) { return NULL; } _FAT_startSector = startSector; // Init the partition lock _FAT_lock_init(&partition->lock); // Set partition's disc interface partition->disc = disc; // Store required information about the file system partition->fat.sectorsPerFat = u8array_to_u16(sectorBuffer, BPB_sectorsPerFAT); if (partition->fat.sectorsPerFat == 0) { partition->fat.sectorsPerFat = u8array_to_u32( sectorBuffer, BPB_FAT32_sectorsPerFAT32); } partition->numberOfSectors = u8array_to_u16( sectorBuffer, BPB_numSectorsSmall); if (partition->numberOfSectors == 0) { partition->numberOfSectors = u8array_to_u32( sectorBuffer, BPB_numSectors); } partition->bytesPerSector = BYTES_PER_READ; // Sector size is redefined to be 512 bytes partition->sectorsPerCluster = sectorBuffer[BPB_sectorsPerCluster] * u8array_to_u16(sectorBuffer, BPB_bytesPerSector) / BYTES_PER_READ; partition->bytesPerCluster = partition->bytesPerSector * partition->sectorsPerCluster; partition->fat.fatStart = startSector + u8array_to_u16(sectorBuffer, BPB_reservedSectors); partition->rootDirStart = partition->fat.fatStart + (sectorBuffer[BPB_numFATs] * partition->fat.sectorsPerFat); partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); partition->totalSize = ((uint64_t)partition->numberOfSectors - (partition->dataStart - startSector)) * (uint64_t)partition->bytesPerSector; // Store info about FAT uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; partition->fat.lastCluster = clusterCount + CLUSTER_FIRST - 1; partition->fat.firstFree = CLUSTER_FIRST; if (clusterCount < CLUSTERS_PER_FAT12) { partition->filesysType = FS_FAT12; // FAT12 volume } else if (clusterCount < CLUSTERS_PER_FAT16) { partition->filesysType = FS_FAT16; // FAT16 volume } else { partition->filesysType = FS_FAT32; // FAT32 volume } if (partition->filesysType != FS_FAT32) { partition->rootDirCluster = FAT16_ROOT_DIR_CLUSTER; } else { // Set up for the FAT32 way partition->rootDirCluster = u8array_to_u32(sectorBuffer, BPB_FAT32_rootClus); // Check if FAT mirroring is enabled if (!(sectorBuffer[BPB_FAT32_extFlags] & 0x80)) { // Use the active FAT partition->fat.fatStart = partition->fat.fatStart + ( partition->fat.sectorsPerFat * (sectorBuffer[BPB_FAT32_extFlags] & 0x0F)); } } // Create a cache to use partition->cache = _FAT_cache_constructor (cacheSize, sectorsPerPage, partition->disc, startSector+partition->numberOfSectors); // Set current directory to the root partition->cwdCluster = partition->rootDirCluster; // Check if this disc is writable, and set the readOnly property appropriately partition->readOnly = !(_FAT_disc_features(disc) & FEATURE_MEDIUM_CANWRITE); // There are currently no open files on this partition partition->openFileCount = 0; partition->firstOpenFile = NULL; return partition; }
bool PartitionHandle::Mount(int pos, const char *name, bool forceFAT) { if(valid(pos)) UnMount(pos); if(!name) return false; if(pos >= (int)MountNameList.size()) MountNameList.resize(pos + 1); MountNameList[pos] = name; char DeviceSyn[10]; memcpy(DeviceSyn, name, 8); strcat(DeviceSyn, ":"); DeviceSyn[9] = '\0'; //! Some stupid partition manager think they don't need to edit the freaken MBR. //! So we need to check the first 64 sectors and see if some partition is there. //! libfat does that by default so let's use it. if(forceFAT && (strlen(GetFSName(pos)) == 0 || strcmp(GetFSName(pos), "Unknown") == 0)) { if(fatMount(MountNameList[pos].c_str(), interface, 0, CACHE, SECTORS)) { sec_t FAT_startSector = FindFirstValidPartition(interface); AddPartition("FAT", FAT_startSector, 0xdeadbeaf, true, 0x0c, 0); gprintf("FAT Partition at %s (forceFAT) mounted.\n", DeviceSyn); SetWbfsHandle(pos, NULL); return true; } } if(!valid(pos)) return false; SetWbfsHandle(pos, NULL); if(strncmp(GetFSName(pos), "FAT", 3) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0) { if(fatMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS)) { gprintf("FAT Partition at %s mounted.\n", DeviceSyn); PartitionList[pos].FSName = "FAT"; return true; } } else if(strncmp(GetFSName(pos), "NTFS", 4) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0) { if(ntfsMount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, NTFS_SHOW_HIDDEN_FILES | NTFS_RECOVER)) { gprintf("NTFS Partition at %s mounted.\n", DeviceSyn); PartitionList[pos].FSName = "NTFS"; return true; } } else if(strncmp(GetFSName(pos), "LINUX", 5) == 0 || strcmp(GetFSName(pos), "GUID-Entry") == 0) { if(ext2Mount(MountNameList[pos].c_str(), interface, GetLBAStart(pos), CACHE, SECTORS, EXT2_FLAG_DEFAULT)) { gprintf("EXT Partition at %s mounted.\n", DeviceSyn); PartitionList[pos].FSName = "LINUX"; return true; } } else if(strncmp(GetFSName(pos), "WBFS", 4) == 0) { if(interface == &__io_usbstorage2_port0 || interface == &__io_usbstorage2_port1) SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadUSB, __WBFS_WriteUSB, NULL, USBStorage2_GetSectorSize(), GetSecCount(pos), GetLBAStart(pos), 0)); else if(interface == &__io_sdhc) SetWbfsHandle(pos, wbfs_open_partition(__WBFS_ReadSDHC, __WBFS_WriteSDHC, NULL, 512, GetSecCount(pos), GetLBAStart(pos), 0)); if(GetWbfsHandle(pos)) { gprintf("WBFS Partition at %s mounted.\n", DeviceSyn); PartitionList[pos].FSName = "WBFS"; return true; } } /* FAIL */ MountNameList[pos].clear(); return false; }