//------------------------------------------------------------------------------
// Store a FAT entry
uint8_t SdVolume::fatPut(uint32_t cluster, uint32_t value) {
  // error if reserved cluster
  if (cluster < 2) 
	  return false;

  // error if not in FAT
  if (cluster > (clusterCount_ + 1)) 
	  return false;

  // calculate block address for entry
  uint32_t lba = fatStartBlock_;
  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;

  if (lba != cacheBlockNumber_) 
  {
    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
  }
  // store entry
  if (fatType_ == 16) 
  {
    cacheBuffer_.fat16[cluster & 0XFF] = value;
  }
  else 
  {
    cacheBuffer_.fat32[cluster & 0X7F] = value;
  }
  cacheSetDirty();

  // mirror second FAT
  if (fatCount_ > 1) 
	  cacheMirrorBlock_ = lba + blocksPerFat_;
  return true;
}
Example #2
0
//------------------------------------------------------------------------------
// Fetch a FAT entry
uint8_t SdVolume::fatGet(uint32_t cluster, uint32_t* value) const {
  if (cluster > (clusterCount_ + 1)) return false;
  uint32_t lba = fatStartBlock_;
  lba += fatType_ == 16 ? cluster >> 8 : cluster >> 7;
  if (lba != cacheBlockNumber_) {
    if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
  }
  if (fatType_ == 16) {
    *value = cacheBuffer_.fat16[cluster & 0XFF];
  } else {
    *value = cacheBuffer_.fat32[cluster & 0X7F] & FAT32MASK;
  }
  return true;
}
Example #3
0
int8_t PLEN2::ExternalSD::writeSlot(uint32_t slot, const uint8_t data[], uint8_t write_size)
{
    uint32_t block;
    uint16_t offset;

    #if DEBUG
        PROFILING("ExternalSD::writeSlot()");
    #endif


    if (   (slot >= SLOT_END)
        || (write_size > SLOT_SIZE)
    )
    {
        #if DEBUG
            System::debugSerial().print(F(">>> bad argument! : slot = "));
            System::debugSerial().print(slot);
            System::debugSerial().print(F(", or write_size = "));
            System::debugSerial().println(write_size);
        #endif

        return -1;
    }

    block  = 32 + (slot * CHUNK_SIZE) / 512;
    offset = (slot * CHUNK_SIZE) % 512;

    #if DEBUG
        System::debugSerial().print(F("writeSlot slot = "));
        System::debugSerial().print(slot);
        System::debugSerial().print(F(", block = "));
        System::debugSerial().print(block);
        System::debugSerial().print(F(", offset = "));
        System::debugSerial().println(offset);
    #endif

    if (cacheRawBlock(block, CACHE_FOR_WRITE)) {
        memcpy(&mCacheBuf[offset], data, write_size);
        cacheFlush();
        return 0;
    }

    return -1;
}
Example #4
0
int8_t PLEN2::ExternalSD::readSlot(uint32_t slot, uint8_t data[], uint8_t read_size)
{
    uint32_t block;
    uint16_t offset;

    #if DEBUG
        PROFILING("ExternalSD::readSlot()");
    #endif


    if (   (slot >= SLOT_END)
        || (read_size > SLOT_SIZE)
    )
    {
        #if DEBUG
            System::debugSerial().print(F(">>> bad argument! : slot = "));
            System::debugSerial().print(slot);
            System::debugSerial().print(F(", or read_size = "));
            System::debugSerial().println(read_size);
        #endif

        return -1;
    }

    block  = 32 + (slot * CHUNK_SIZE) / 512;
    offset = (slot * CHUNK_SIZE) % 512;

    #if DEBUG
        System::debugSerial().print(F("readSlot slot = "));
        System::debugSerial().print(slot);
        System::debugSerial().print(F(", block = "));
        System::debugSerial().print(block);
        System::debugSerial().print(F(", offset = "));
        System::debugSerial().println(offset);
    #endif

    if (cacheRawBlock(block, CACHE_FOR_READ)) {
        memcpy(data, &mCacheBuf[offset], read_size);
        return read_size;
    }

    return -1;
}
/**
 * Initialize a FAT volume.
 *
 * \param[in] dev The SD card where the volume is located.
 *
 * \param[in] part The partition to be used.  Legal values for \a part are
 * 1-4 to use the corresponding partition on a device formatted with
 * a MBR, Master Boot Record, or zero if the device is formatted as
 * a super floppy with the FAT boot sector in block zero.
 *
 * \return The value one, true, is returned for success and
 * the value zero, false, is returned for failure.  Reasons for
 * failure include not finding a valid partition, not finding a valid
 * FAT file system in the specified partition or an I/O error.
 */
uint8_t SdVolume::init(Sd2Card* dev, uint8_t part) 
{
  uint32_t volumeStartBlock = 0;
  sdCard_ = dev;
  // if part == 0 assume super floppy with FAT boot sector in block zero
  // if part > 0 assume mbr volume with partition table
  if (part) 
  {
    if (part > 4)
	{
		DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() MBR");
		return false;
	}

    if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) 
	{
		DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() Cache for read");
		return false;
	}

    part_t* p = &cacheBuffer_.mbr.part[part-1];
	
	if ((p->boot & 0X7F) !=0  ||
      p->totalSectors < 100 ||
      p->firstSector == 0) 
	{
      // not a valid partition
	
	  DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() Invalid partition");
	  return false;
    }
	volumeStartBlock = p->firstSector;
  }
  if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) 
  {
	  DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() Cache for read2");
	  return false;
  }

  bpb_t* bpb = &cacheBuffer_.fbs.bpb;
  if (bpb->bytesPerSector != 512 ||
    bpb->fatCount == 0 ||
    bpb->reservedSectorCount == 0 ||
    bpb->sectorsPerCluster == 0) 
  {
       // not valid FAT volume
      DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() invalid FAT volume");
      return false;
  }
  fatCount_ = bpb->fatCount;
  blocksPerCluster_ = bpb->sectorsPerCluster;

  // determine shift that is same as multiply by blocksPerCluster_
  clusterSizeShift_ = 0;
  while (blocksPerCluster_ != (1 << clusterSizeShift_)) 
  {
    // error if not power of 2
    if (clusterSizeShift_++ > 7) 
	{
		return false;
		DEBUG_SDFAT_PRINTLN("Error: SdVolume::init() not power of 2");
	}
  }
  blocksPerFat_ = bpb->sectorsPerFat16 ?
                    bpb->sectorsPerFat16 : bpb->sectorsPerFat32;

  fatStartBlock_ = volumeStartBlock + bpb->reservedSectorCount;

  // count for FAT16 zero for FAT32
  rootDirEntryCount_ = bpb->rootDirEntryCount;

  // directory start for FAT16 dataStart for FAT32
  rootDirStart_ = fatStartBlock_ + bpb->fatCount * blocksPerFat_;

  // data start for FAT16 and FAT32
  dataStartBlock_ = rootDirStart_ + ((32 * bpb->rootDirEntryCount + 511)/512);

  // total blocks for FAT16 or FAT32
  uint32_t totalBlocks = bpb->totalSectors16 ?
                           bpb->totalSectors16 : bpb->totalSectors32;
  // total data blocks
  clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);

  // divide by cluster size to get cluster count
  clusterCount_ >>= clusterSizeShift_;

  // FAT type is determined by cluster count
  if (clusterCount_ < 4085) 
  {
    fatType_ = 12;
  } 
  else if (clusterCount_ < 65525) 
  {
    fatType_ = 16;
  }
  else 
  {
    rootDirStart_ = bpb->fat32RootCluster;
    fatType_ = 32;
  }
  return true;
}