Beispiel #1
0
/**
 * This fills the file's currentFATData buffer with the next block of FAT data to write.
 * If the next block is not the previously predicted block, then the previousFATData
 * cache is modified to account for this, and the previousFATDirty byte is set to 1.
 * If the cluster pointer to the beginning of the next block does not reside at
 * the beginning block boundary, the entire block is read in and the relevant portions
 * are updated.
 *
 * @param file File to fill for.
 * @return Number of clusters allocated
 */
uint16_t FAT32_AllocateFATBlock(FAT32FileOpt *file) {
	uint16_t clusterPointer;
	uint32_t nextCluster = file->fs->mostRecentCluster + 1;
	uint16_t numAllocatedClusters = 0;

	// Check next cluster allocated against the last cluster link
	if (FATDataToInt32(file->previousFATBlockData + file->previousFATBlockOffset) != nextCluster) {
		Int32ToFATData(file->previousFATBlockData + file->previousFATBlockOffset, nextCluster);
		file->previousFATDirty = 1;
	}

	clusterPointer = GetClusterFATOffset(file->fs, nextCluster);
	file->currentFATLBA = GetClusterFATLBA(file->fs, nextCluster);
	// If the next cluster pointer isn't on a block boundary, read in the current entries in the block
	if (clusterPointer != 0) {
		DBG_DATA_printf("Reading in FAT data at LBA=0x%08lx (cluster=0x%08lx, offset=0x%04x)",
				file->currentFATLBA, nextCluster, clusterPointer);
		// TODO Make this DMA Friendly
		if (BLOCK_SIZE != SD_SPI_ReadSingleBlock(file->fs->card, file->currentFATLBA, file->currentFATBlockData)) {
			DBG_ERR_printf("Error creating file (SD Read error on LBA = 0x%08lx).", file->currentFATLBA);
			return -1;			// Sanity check: Not reading the correct number of bytes
		}
	}

	// Fill in file table data
	file->nextClusterBegin = file->fs->mostRecentCluster + 1;
	for (;clusterPointer<BLOCK_SIZE;clusterPointer+=file->fs->clusterPointerSize) {
		nextCluster++;
		Int32ToFATData(file->currentFATBlockData+clusterPointer, nextCluster);
	}
	file->currentFATBlockOffset = clusterPointer - file->fs->clusterPointerSize;
	file->nextClusterEnd = nextCluster - 1;

	// Mark as allocated
	file->currentFATAllocated = 1;
	file->currentFATDirty = 1;

	// Compute new file size
	numAllocatedClusters = (file->nextClusterEnd - file->nextClusterBegin) + 1;
	file->size += (uint32_t)numAllocatedClusters * file->fs->bytesPerSector * file->fs->sectorsPerCluster;
	FAT32_UpdateDirectoryTableEntry(file);

	// Update FS Information sector
	file->fs->mostRecentCluster = file->nextClusterEnd;
	file->fs->numFreeClusters -= numAllocatedClusters;
	file->fs->fsInfoDirty = 1;

	DBG_DATA_printf("Allocated clusters 0x%08lx to 0x%08lx (FAT LBA=0x%08lx), file size=%lu)",
			file->nextClusterBegin, file->nextClusterEnd, file->currentFATLBA, file->size);
	DBG_DATA_printf("Most recent cluster=0x%08lx, num free clusters=%lu", file->fs->mostRecentCluster, file->fs->numFreeClusters);

	return numAllocatedClusters;
}
void FAT32_AllocateFATBlock(FS_File *file, uint8_t *data) {
	uint32_t currCluster = file->currCluster;
	uint16_t pos = GetClusterFATOffset(file->fs, currCluster);

	file->fs->numFreeClusters -= (file->fs->bytesPerSector - pos) /
			file->fs->clusterPointerSize;
	file->currFATLBA = GetClusterFATLBA(file->fs, currCluster);
	
	for (;pos<file->fs->bytesPerSector;pos+=file->fs->clusterPointerSize) {
		currCluster++;
		Int32ToFATData(data+pos, currCluster);
	}
	currCluster--;
	pos -= file->fs->clusterPointerSize;

	file->currFATBlockOffset = pos;
	file->currFATClusterEnd = currCluster;
	file->fs->mostRecentCluster = currCluster;
	file->fs->fsInfoDirty = 1;
}
void FAT32_TerminateFATBlock(FS_File *file, uint8_t *data) {
	uint32_t currCluster = file->currCluster;
	uint16_t pos = GetClusterFATOffset(file->fs, currCluster);
	uint16_t end = GetClusterFATOffset(file->fs, file->currFATClusterEnd);

	file->fs->numFreeClusters -= (end - pos) / file->fs->clusterPointerSize;
	file->currFATLBA = GetClusterFATLBA(file->fs, currCluster);

	Int32ToFATData(data+pos, FAT32_CLUSTER_EOC);
	file->currFATClusterEnd = FAT32_CLUSTER_EOC;

	file->currFATBlockOffset = pos;
	file->fs->mostRecentCluster = currCluster;
	file->fs->fsInfoDirty = 1;

	pos += file->fs->clusterPointerSize;

	for (;pos<=end;pos+=file->fs->clusterPointerSize) {
		Int32ToFATData(data+pos, 0x00000000);
	}
}