LUFA Library - Mass Storage Class Bootloader
VirtualFAT.c File Reference
#include "VirtualFAT.h"

Functions

static uint8_t ReadEEPROMByte (const uint8_t *const Address)
 
static void WriteEEPROMByte (uint8_t *const Address, const uint8_t Data)
 
static void UpdateFAT12ClusterEntry (uint8_t *const FATTable, const uint16_t Index, const uint16_t ChainEntry)
 
static void UpdateFAT12ClusterChain (uint8_t *const FATTable, const uint16_t Index, const uint8_t ChainLength)
 
static void ReadWriteFLASHFileBlock (const uint16_t BlockNumber, uint8_t *BlockBuffer, const bool Read)
 
static void ReadWriteEEPROMFileBlock (const uint16_t BlockNumber, uint8_t *BlockBuffer, const bool Read)
 
void VirtualFAT_WriteBlock (const uint16_t BlockNumber)
 
void VirtualFAT_ReadBlock (const uint16_t BlockNumber)
 

Variables

static const FATBootBlock_t BootBlock
 
static FATDirectoryEntry_t FirmwareFileEntries []
 
static const uint16_t * FLASHFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster
 
static const uint16_t * EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster
 

Detailed Description

Virtualized FAT12 filesystem implementation, to perform self-programming in response to read and write requests to the virtual filesystem by the host PC.

Function Documentation

static uint8_t ReadEEPROMByte ( const uint8_t *const  Address)
static

Reads a byte of EEPROM out from the EEPROM memory space.

Note
This function is required as the avr-libc EEPROM functions do not cope with linker relaxations, and a jump longer than 4K of FLASH on the larger USB AVRs will break the linker. This function is marked as never inlinable and placed into the normal text segment so that the call to the EEPROM function will be short even if the AUX boot section is used.
Parameters
[in]AddressAddress of the EEPROM location to read from
Returns
Read byte of EEPROM data.
static void ReadWriteEEPROMFileBlock ( const uint16_t  BlockNumber,
uint8_t *  BlockBuffer,
const bool  Read 
)
static

Reads or writes a block of data from/to the physical device EEPROM using a block buffer stored in RAM, if the requested block is within the virtual firmware file's sector ranges in the emulated FAT file system.

Parameters
[in]BlockNumberPhysical disk block to read from/write to
[in,out]BlockBufferPointer to the start of the block buffer in RAM
[in]ReadIf true, the requested block is read, if false, the requested block is written
static void ReadWriteFLASHFileBlock ( const uint16_t  BlockNumber,
uint8_t *  BlockBuffer,
const bool  Read 
)
static

Reads or writes a block of data from/to the physical device FLASH using a block buffer stored in RAM, if the requested block is within the virtual firmware file's sector ranges in the emulated FAT file system.

Parameters
[in]BlockNumberPhysical disk block to read from/write to
[in,out]BlockBufferPointer to the start of the block buffer in RAM
[in]ReadIf true, the requested block is read, if false, the requested block is written
static void UpdateFAT12ClusterChain ( uint8_t *const  FATTable,
const uint16_t  Index,
const uint8_t  ChainLength 
)
static

Updates a FAT12 cluster chain in the FAT file table with a linear chain of the specified length.

Note
FAT data cluster indexes are offset by 2, so that cluster 2 is the first file data cluster on the disk. See the FAT specification.
Parameters
[out]FATTablePointer to the FAT12 allocation table
[in]IndexIndex of the start of the cluster chain to update
[in]ChainLengthLength of the chain to write, in clusters
static void UpdateFAT12ClusterEntry ( uint8_t *const  FATTable,
const uint16_t  Index,
const uint16_t  ChainEntry 
)
static

Updates a FAT12 cluster entry in the FAT file table with the specified next chain index. If the cluster is the last in the file chain, the magic value 0xFFF should be used.

Note
FAT data cluster indexes are offset by 2, so that cluster 2 is the first file data cluster on the disk. See the FAT specification.
Parameters
[out]FATTablePointer to the FAT12 allocation table
[in]IndexIndex of the cluster entry to update
[in]ChainEntryNext cluster index in the file chain
void VirtualFAT_ReadBlock ( const uint16_t  BlockNumber)

Reads a block of data from the virtual FAT filesystem, and sends it to the host via the USB Mass Storage interface.

Parameters
[in]BlockNumberIndex of the block to read.
void VirtualFAT_WriteBlock ( const uint16_t  BlockNumber)

Writes a block of data to the virtual FAT filesystem, from the USB Mass Storage interface.

Parameters
[in]BlockNumberIndex of the block to write.
static void WriteEEPROMByte ( uint8_t *const  Address,
const uint8_t  Data 
)
static

Writes a byte of EEPROM out to the EEPROM memory space.

Note
This function is required as the avr-libc EEPROM functions do not cope with linker relaxations, and a jump longer than 4K of FLASH on the larger USB AVRs will break the linker. This function is marked as never inlinable and placed into the normal text segment so that the call to the EEPROM function will be short even if the AUX boot section is used.
Parameters
[in]AddressAddress of the EEPROM location to write to
[in]DataNew data to write to the EEPROM location

Variable Documentation

const FATBootBlock_t BootBlock
static
Initial value:
=
{
.Bootstrap = {0xEB, 0x3C, 0x90},
.Description = "mkdosfs",
.SectorSize = SECTOR_SIZE_BYTES,
.SectorsPerCluster = SECTOR_PER_CLUSTER,
.ReservedSectors = 1,
.FATCopies = 2,
.RootDirectoryEntries = (SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t)),
.TotalSectors16 = LUN_MEDIA_BLOCKS,
.MediaDescriptor = 0xF8,
.SectorsPerFAT = 1,
.SectorsPerTrack = (LUN_MEDIA_BLOCKS % 64),
.Heads = (LUN_MEDIA_BLOCKS / 64),
.HiddenSectors = 0,
.TotalSectors32 = 0,
.PhysicalDriveNum = 0,
.ExtendedBootRecordSig = 0x29,
.VolumeSerialNumber = 0x12345678,
.VolumeLabel = "LUFA BOOT ",
.FilesystemIdentifier = "FAT12 ",
}

FAT filesystem boot sector block, must be the first sector on the physical disk so that the host can identify the presence of a FAT filesystem. This block is truncated; normally a large bootstrap section is located near the end of the block for booting purposes however as this is not meant to be a bootable disk it is omitted for space reasons.

Note
When returning the boot block to the host, the magic signature 0xAA55 must be added to the very end of the block to identify it as a boot block.
const uint16_t* EEPROMFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_EEPROM_MSDOS].MSDOS_File.StartingCluster
static

Starting cluster of the virtual EEPROM.BIN file on disk, tracked so that the offset from the start of the data sector can be determined. On Windows systems files are usually replaced using the original file's disk clusters, while Linux appears to overwrite with an offset which must be compensated for.

FATDirectoryEntry_t FirmwareFileEntries[]
static

FAT 8.3 style directory entry, for the virtual FLASH contents file.

const uint16_t* FLASHFileStartCluster = &FirmwareFileEntries[DISK_FILE_ENTRY_FLASH_MSDOS].MSDOS_File.StartingCluster
static

Starting cluster of the virtual FLASH.BIN file on disk, tracked so that the offset from the start of the data sector can be determined. On Windows systems files are usually replaced using the original file's disk clusters, while Linux appears to overwrite with an offset which must be compensated for.