Exemple #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;
}
Exemple #2
0
/**
 * Fills the FS buffer with the updated FS Information Sector for FAT32.
 * @param file File.
 */
void FAT32_FillFSInformationSector(FAT32FileOpt *file) {
	uint16_t i = 0;
	file->fsBuffer[0x00] = 0x52;
	file->fsBuffer[0x01] = 0x52;
	file->fsBuffer[0x02] = 0x61;
	file->fsBuffer[0x03] = 0x41;
	for (i=0x04;i<0x1e4;i++) {
		file->fsBuffer[i] = 0x00;
	}
	file->fsBuffer[0x1e4] = 0x72;
	file->fsBuffer[0x1e5] = 0x72;
	file->fsBuffer[0x1e6] = 0x61;
	file->fsBuffer[0x1e7] = 0x41;
	Int32ToFATData(file->fsBuffer + 0x1e8, file->fs->numFreeClusters);
	Int32ToFATData(file->fsBuffer + 0x1ec, file->fs->mostRecentCluster);
	for (i=0x1f0;i<0x1fe;i++) {
		file->fsBuffer[i] = 0x00;
	}
	file->fsBuffer[0x1fe] = 0x55;
	file->fsBuffer[0x1ff] = 0xaa;
}
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);
	}
}
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;
}
Exemple #5
0
void FAT32_Terminate(FAT32FileOpt *file) {
	DBG_DATA_printf("Terminate: data buffers remaining=%u", file->dataBufferNumFilled);

	// Wait for all outstanding buffers to be committed to disk.
	while (file->dataBufferNumFilled > 0 || file->overflowBufferSize > 0) {
		FAT32_MoveOverflowToData(file);
		FAT32_Tasks(file);
	}
	
	// If last buffer is partially full, zero the rest of the data and commit it.
	if (file->dataBufferPos > 0) {
		uint16_t pos = file->dataBufferPos;
		uint16_t zeroFill = file->fs->bytesPerSector - file->dataBufferPos;
		DBG_DATA_printf("Terminate: partial data buffer, position=%u", file->dataBufferPos);

		for (pos = file->dataBufferPos; pos<file->fs->bytesPerSector; pos++) {
			file->dataBuffer[file->dataBufferFill][pos] = 0;
		}
		file->dataBufferNumFilled++;
		file->dataBufferFill++;
		if (file->dataBufferFill >= FAT32_NUM_DATA_BUFFERS) {
			file->dataBufferFill = 0;
		}
		while (file->dataBufferNumFilled > 0) {
			FAT32_Tasks(file);
		}
		file->position -= zeroFill;
	}

	DBG_DATA_printf("Terminate: stopping DMA MBW operations");
	SD_DMA_MBW_End();
	while (SD_DMA_MBW_GetBlockStatus() == 0x00);

	// Update file size
	file->size = file->position;
	FAT32_UpdateDirectoryTableEntry(file);
	DBG_DATA_printf("Terminate: Updating directory table at LBA=0x%08lx, file size=0x%08lx",
			file->directoryTableLBA, file->size);
	SD_SPI_WriteSingleBlock(file->fs->card, file->directoryTableLBA, file->directoryTableBlockData);
	file->directoryTableDirty = 0;

	// Update FAT
	// Deallocate unused clusters
	uint16_t clusterBegin = GetClusterFATOffset(file->fs, file->currentCluster);
	DBG_DATA_printf("Terminate: Deallocating previous FAT block starting cluster=0x%08lx, offset=%u",
			file->currentCluster, clusterBegin);
	Int32ToFATData(file->previousFATBlockData + clusterBegin, 0x0fffffff);
	clusterBegin+= file->fs->clusterPointerSize;
	for (; clusterBegin < file->fs->bytesPerSector; clusterBegin += file->fs->clusterPointerSize) {
		Int32ToFATData(file->previousFATBlockData + clusterBegin, 0x00000000);
	}
	DBG_DATA_printf("Terminate: Updating previous FAT block at LBA=0x%08lx", file->previousFATLBA);
	SD_SPI_WriteSingleBlock(file->fs->card, file->previousFATLBA, file->previousFATBlockData);

	// Deallocate the next block
	if (file->currentFATAllocated && !file->currentFATDirty) {
		DBG_DATA_printf("Terminate: Deallocating current FAT block");
		for (clusterBegin = 0; clusterBegin < file->fs->bytesPerSector; clusterBegin += file->fs->clusterPointerSize) {
			Int32ToFATData(file->currentFATBlockData + clusterBegin, 0x00000000);
		}
		DBG_DATA_printf("Terminate: Updating current FAT block at LBA=0x%08lx", file->currentFATLBA);
		SD_SPI_WriteSingleBlock(file->fs->card, file->currentFATLBA, file->currentFATBlockData);
	}
	
	// Update FS Information Sector
	file->fs->mostRecentCluster = file->currentCluster;
	
}
Exemple #6
0
/**
 * Updates the file's directory table entry with current paramters like size.
 * @param file File for which the directory table entry is updated.
 */
void FAT32_UpdateDirectoryTableEntry(FAT32FileOpt *file) {
	Int32ToFATData(file->directoryTableBlockData + file->directoryTableBlockOffset + 0x1c, file->size);
	file->directoryTableDirty = 1;
}
void FAT32_UpdateDirectoryTableEntry(FS_File *file, uint8_t *data) {
	Int32ToFATData(data + file->dirTableBlockOffset + 0x1c, file->size);
}