Пример #1
0
// Initialize the library - locates the first FAT16 partition,
// loads the relevant part of its boot sector to calculate
// values needed for operation, and finally positions the
// file reading routines to the start of root directory entries
char fat16_init() {
    char i;
    unsigned long root_start;
    
    fat16_seek(0x1BE);
        
    for(i=0; i<4; i++) {        
        fat16_read(sizeof(PartitionTable));
        
        if(FAT16_part->partition_type == 4 || 
           FAT16_part->partition_type == 6 ||
           FAT16_part->partition_type == 14)
            break;
    }
    
    if(i == 4) // none of the partitions were FAT16
        return FAT16_ERR_NO_PARTITION_FOUND;
    
    fat16_state.fat_start = 512 * FAT16_part->start_sector; // temporary
    
    fat16_seek(fat16_state.fat_start + FAT16_BOOT_OFFSET);
    fat16_read(sizeof(Fat16BootSectorFragment));
    
    if(FAT16_boot->sector_size != 512)
        return FAT16_ERR_INVALID_SECTOR_SIZE;
    
    fat16_state.fat_start += FAT16_boot->reserved_sectors * 512;
    
    root_start = fat16_state.fat_start + FAT16_boot->fat_size_sectors * 
        FAT16_boot->number_of_fats * 512;
    
    fat16_state.data_start = root_start + FAT16_boot->root_dir_entries * 
        sizeof(Fat16Entry);
        
    fat16_state.sectors_per_cluster = FAT16_boot->sectors_per_cluster;
    
    // Prepare for fat16_open_file(), cluster is not needed
    fat16_state.file_left = FAT16_boot->root_dir_entries * sizeof(Fat16Entry);
    fat16_state.cluster_left = 0xFFFFFFFF; // avoid FAT lookup with root dir

#ifdef DEBUG    
    printf("FAT start at %08X, root dir at %08X, data at %08X\n", 
           fat16_state.fat_start, root_start, fat16_state.data_start);
#endif
           
    fat16_seek(root_start);

    return 0;
}
Пример #2
0
// Assumes we are at the beginning of a directory and fat16_state.file_left
// is set to amount of file entries. Reads on until a given file is found,
// or no more file entries are available.
char fat16_open_file(char *filename, char *ext) {  
    char i, bytes;
    
#ifdef DEBUG
    printf("Trying to open file [%s.%s]\n", filename, ext);
#endif

    do {
        bytes = fat16_read_file(sizeof(Fat16Entry));
        
        if(bytes < sizeof(Fat16Entry))
            return FAT16_ERR_FILE_READ;
		
#ifdef DEBUG
        if(FAT16_entry->filename[0])
            printf("Found file [%.8s.%.3s]\n", FAT16_entry->filename, FAT16_entry->ext);
#endif

        for(i=0; i<8; i++) // we don't have memcmp on a MCU...
            if(FAT16_entry->filename[i] != filename[i])
                break;        
        if(i < 8) // not the filename we are looking for
            continue;
		
        for(i=0; i<3; i++) // we don't have memcmp on a MCU...
            if(FAT16_entry->ext[i] != ext[i])
                break;
        if(i < 3) // not the extension we are looking for
            continue;
            
#ifdef DEBUG
        printf("File found at cluster %d!\n", FAT16_entry->starting_cluster);
#endif

        // Initialize reading variables
        fat16_state.cluster = FAT16_entry->starting_cluster;
        fat16_state.cluster_left = fat16_state.sectors_per_cluster * 512;
        
        if(FAT16_entry->filename[0] == 0x2E || 
           FAT16_entry->attributes & 0x10) { // directory
            // set file size so large that the file entries
            // are not limited by it, but by the sectors used
            fat16_state.file_left = 0xFFFFFFFF;
        } else {
            fat16_state.file_left = FAT16_entry->file_size;
        }
        
        // Go to first cluster
        fat16_seek(fat16_state.data_start + (fat16_state.cluster-2) * 
            fat16_state.sectors_per_cluster * 512);
        return 0;
    } while(fat16_state.file_left > 0);
    
#ifdef DEBUG    
    printf("File not found: [%s.%s]!\n", filename, ext);
#endif
    
    return FAT16_ERR_FILE_NOT_FOUND;
}
Пример #3
0
char fat16_read_file(char bytes) { // returns the bytes read
#ifdef DEBUG   
    //printf("fat16_read_file: Cluster %d, bytes left %d/%d\n", fat16_state.cluster, fat16_state.file_left, fat16_state.cluster_left);
#endif
 
    if(fat16_state.file_left == 0)
        return 0;
    
    if(fat16_state.cluster_left == 0) {
        fat16_seek(fat16_state.fat_start + fat16_state.cluster*2);
        fat16_read(2);
        
        fat16_state.cluster = FAT16_ushort[0];
        fat16_state.cluster_left = fat16_state.sectors_per_cluster * 512;
        
        if(fat16_state.cluster == 0xFFFF) { // end of cluster chain
            fat16_state.file_left = 0;
            return 0;
        }
            
        // Go to first cluster
        fat16_seek(fat16_state.data_start + (fat16_state.cluster-2) * 
            fat16_state.sectors_per_cluster * 512);
        
#ifdef DEBUG    
        printf("Next cluster %d\n", fat16_state.cluster);
#endif
    }
    
    if(bytes > fat16_state.file_left)
        bytes = fat16_state.file_left;
    if(bytes > fat16_state.cluster_left)
        bytes = fat16_state.cluster_left;
        
    bytes = fat16_read(bytes);
    
    fat16_state.file_left -= bytes;
    fat16_state.cluster_left -= bytes;

#ifdef DEBUG   
    //printf("%d bytes read: Cluster %d, bytes left %d/%d\n", bytes, fat16_state.cluster, fat16_state.file_left, fat16_state.cluster_left);
#endif
    
    return bytes;
}
Пример #4
0
uint8_t fat16_read_file(struct fat16_buffer* buffer, uint8_t* data)
{
	if (buffer->file_left == 0)
	{
		return 0;
	}

	if (buffer->cluster_offset == FAT16_CLUSTER_SIZE)
	{
		// look up the next cluster (current cluster * 2 bytes)
		fat16_seek(buffer, buffer->fat_start + buffer->current_cluster * 2);
		fat16_read16(buffer, &buffer->current_cluster);
		buffer->cluster_offset = 0;
		if (buffer->current_cluster == 0xffff)
		{
			// done reading!
			return 0;
		}
	}

	uint32_t data_start = buffer->directory_start + 16384;
	data_start += ((buffer->current_cluster - 2) * FAT16_CLUSTER_SIZE) + buffer->cluster_offset;

	fat16_seek(buffer, data_start);

	uint8_t bytes_to_read;
	if (buffer->file_left > FAT16_BUFFER_SIZE)
	{
		bytes_to_read = FAT16_BUFFER_SIZE;
	}
	else
	{
		bytes_to_read = buffer->file_left;
	}
	fat16_read(buffer, bytes_to_read);
	for (uint8_t index = 0; index < bytes_to_read; ++index)
	{
		data[index] = buffer->data[index];
	}

	buffer->cluster_offset += bytes_to_read;
	buffer->file_left -= bytes_to_read;
	return bytes_to_read;
} // fat16_read_file
Пример #5
0
int8_t fat16_init(struct fat16_buffer* buffer)
{
	uint8_t partition_type;
	uint32_t partition_start_sector;
	uint16_t boot_sector_signature;
	uint16_t reserved_sectors;
	uint16_t fat_id; // used to help debug fat start
	uint16_t fat_sector_size;

	// seek to the partition table at an absolute offset of 0x1BE
	fat16_seek(buffer, 0x1BE);

	// read the first partition's type (0x1BE + 4)
	fat16_seek(buffer, 0x1BE + 4);
	fat16_read8(buffer, &partition_type);
	fprintf(stdout, "partition type is: %i\n", partition_type);
	if (partition_type != PT_FAT16_DOS331
		// && partition_type != PT_FAT32_LBA // No support for FAT32 LBA yet
		)
	{
		fprintf(stdout, "Unknown partition type: 0x%x\n", partition_type);
		return -1;
	}

	// read the first partition's start sector; offset at (0x1BE + 8)
	fat16_seek(buffer, 0x1BE + 8);
	fat16_read32(buffer, &partition_start_sector);

	// seek 14-bytes into the boot sector record so we can
	// read the # of reserved sectors. this code assumes it is 2.
	fat16_seek(buffer, (512 * partition_start_sector) + 14);
	fat16_read16(buffer, &reserved_sectors);
	ASSERT(reserved_sectors == 2);

	// read the fat sector size: 22 bytes into the boot sector
	fat16_seek(buffer, (512 * partition_start_sector) + 22);
	fat16_read16(buffer, &fat_sector_size);

	// seek the start of the first partition (and skip past the boot sector)
	// the boot sector record is 512 bytes.
	// we back up two bytes so we can verify the boot sector signature.
	fat16_seek(buffer, (512 * (partition_start_sector + 1) - 2));
	fat16_read16(buffer, &boot_sector_signature);
	ASSERT(boot_sector_signature == 0xaa55);

	// Find the FAT: file allocation table. Seek past all the reserved sectors.
	// FAT should start with: 0xFFF8 0xFFFF
	buffer->fat_start = (512 * (partition_start_sector + reserved_sectors));
	fat16_seek(buffer, buffer->fat_start);
	fat16_read16(buffer, &fat_id);
	ASSERT(fat_id == 0xfff8);

	// Skip past file allocation tables and reserved sectors on partition.
	// There are always 2 FATs; 239 sectors per fat
	buffer->directory_start = (512 * (partition_start_sector + reserved_sectors) + (512 * (2 * fat_sector_size)));
	return 0;
} // fat16_init
Пример #6
0
uint32_t fat16_open_file(struct fat16_buffer* buffer, const char* filename, const char* extension)
{
	for (uint16_t file_index = 0; file_index < 512; ++file_index)
	{
		uint8_t pos;
		fat16_seek(buffer, buffer->directory_start + (file_index * 32));
		fat16_read(buffer, 32);

		// attributes is non-zero on files.
		if (buffer->data[11] > 0)
		{
			for (pos = 0; pos < 8; ++pos)
			{
				if (buffer->data[pos] != filename[pos])
				{
					break;
				}
			}

			if (pos == 8)
			{
				// found the entry!
				for (pos = 0; pos < 3; ++pos)
				{
					if (buffer->data[8 + pos] != extension[pos])
					{
						break;
					}
				}

				if (pos == 3)
				{
					// 2 bytes for cluster at buffer.data[26]
					// 4 bytes for file size at buffer.data[28]
					buffer->cluster_offset = 0;
					buffer->current_cluster = (buffer->data[26] | ((uint16_t)buffer->data[27]) << 8);
					buffer->file_left = (buffer->data[28] |
						((uint32_t)buffer->data[29]) << 8 |
						((uint32_t)buffer->data[30]) << 16 |
						((uint32_t)buffer->data[31]) << 24);
					return buffer->file_left;
				}
			}
		}
	}
	return 0;
} // fat16_open_file
Пример #7
0
int8_t fat32_init(struct fat32_buffer* buffer)
{
	// A FAT system volume is composed of four basic regions.
	// reserved region:
	//		Sector 0: boot sector and BIOS Parameter Block
	//		Sector 1: FSInfo sector (FAT32)
	// FAT region
	// root directory region (non-existent on FAT32)
	// file and directory data region

	// Determine if there's an MBR present. This is inconsistent
	// but this doesn't need to be there for removable drives.
	fat32_read(buffer, 3);
	if (buffer->data[0] != 0 ||
		buffer->data[1] != 0 ||
		buffer->data[2] != 0)
	{
		// No MBR present; rewind and start reading the boot sector.
		fat32_seek(buffer, 0);
	}
	else
	{
		// Skip ahead to read the first partition's type.
		fat32_seek(buffer, 0x1BE + 4);

		uint8_t partition_type;
		fat32_read8(buffer, &partition_type);
		fprintf(stdout, "partition type is: %i\n", partition_type);

		fprintf(stdout, "No support for MBR reading at this time.\n");
		return -1;
	}

	// We need to read some values from the Boot Sector and
	// BIOS Parameter Block.

	fat32_seek(buffer, 11);
	fat32_read16(buffer, &buffer->sector_size_bytes);
	fprintf(stdout, "sector size: %i bytes\n", buffer->sector_size_bytes);

	fat32_seek(buffer, 13);
	fat32_read8(buffer, &buffer->sectors_per_cluster);
	fprintf(stdout, "sectors per cluster: %i bytes\n", buffer->sectors_per_cluster);

	fat32_seek(buffer, 14);
	fat32_read16(buffer, &buffer->reserved_sectors);
	fprintf(stdout, "reserved sectors: %i\n", buffer->reserved_sectors);

	fat32_seek(buffer, 16);
	fat32_read8(buffer, &buffer->num_fats);
	fprintf(stdout, "num fats: %i\n", buffer->num_fats);

	fat32_seek(buffer, 36);
	fat32_read32(buffer, &buffer->fat_sectors);
	fprintf(stdout, "fat sectors: %lu\n", buffer->fat_sectors);

	fat32_seek(buffer, 44);
	fat32_read32(buffer, &buffer->root_cluster_index);
	fprintf(stdout, "root cluster index: %lu\n", buffer->root_cluster_index);

	// FAT32 assertions. We skip that here since this will run on embedded,
	// but in case weird problems arise; this will serve as a reference.
	// 1. bytes_per_sector * sectors_per_cluster must be <= 32768
	// 2. root_directory_entries must be zero on FAT32

	buffer->first_data_sector_index = buffer->reserved_sectors + (buffer->num_fats * buffer->fat_sectors);
	fprintf(stdout, "first data sector index: %lu\n", buffer->first_data_sector_index);

#if 0
	// read the first partition's type (0x1BE + 4)
	fat32_seek(buffer, 0x1BE + 4);
	fat32_read8(buffer, &partition_type);
	if (partition_type == PT_FAT32_CHS)
	{
		fprintf(stdout, "<= 2GB partitions are not supported.\n");
		return -1;
	}

	if (partition_type != PT_FAT32_LBA)
	{
		fprintf(stdout, "Unsupported partition type: 0x%x\n", partition_type);
		return -1;
	}

	// read the first partition's start sector; offset at (0x1BE + 8)
	fat32_seek(buffer, 0x1BE + 8);
	fat32_read32(buffer, &partition_start_sector);


	fat32_seek(buffer, (0x1BE + 64 + partition_start_sector));

	struct fat32_boot_sector boot_sector;
	fat32_read_direct(buffer, &boot_sector, sizeof(struct fat32_boot_sector));
#endif

#if 0

	fat32_seek(buffer, (512 * partition_start_sector) + 0x0B);
	fat32_read16(buffer, &buffer->sector_size_bytes);

	fat32_seek(buffer, (512 * partition_start_sector) + 0x0D);
	fat32_read16(buffer, &buffer->sectors_per_cluster);

	// seek 14-bytes into the boot sector record so we can
	// read the # of reserved sectors. this code assumes it is 2.
	fat32_seek(buffer, (512 * partition_start_sector) + 14);
	fat32_read16(buffer, &reserved_sectors);
	ASSERT(reserved_sectors == 2);




	// read the fat sector size: 22 bytes into the boot sector
	fat16_seek(buffer, (512 * partition_start_sector) + 22);
	fat16_read16(buffer, &fat_sector_size);

	// seek the start of the first partition (and skip past the boot sector)
	// the boot sector record is 512 bytes.
	// we back up two bytes so we can verify the boot sector signature.
	fat16_seek(buffer, (512 * (partition_start_sector + 1) - 2));
	fat16_read16(buffer, &boot_sector_signature);
	ASSERT(boot_sector_signature == 0xaa55);


	// Find the FAT: file allocation table. Seek past all the reserved sectors.
	// FAT should start with: 0xFFF8 0xFFFF
	buffer->fat_start = (512 * (partition_start_sector + reserved_sectors));
	fat16_seek(buffer, buffer->fat_start);
	fat16_read16(buffer, &fat_id);
	ASSERT(fat_id == 0xfff8);

	// Skip past file allocation tables and reserved sectors on partition.
	// There are always 2 FATs; 239 sectors per fat
	buffer->directory_start = (512 * (partition_start_sector + reserved_sectors) + (512 * (2 * fat_sector_size)));
#endif
	return 0;
}