X-Git-Url: http://git.linex4red.de/pub/lufa.git/blobdiff_plain/64f17a679f0d99741fb8101f02dfb3ef084e525c..726b325c73d2f6a2a733e67d1dad9fa7aedef1c0:/Bootloaders/Incomplete/MassStorage/Lib/VirtualFAT.c diff --git a/Bootloaders/Incomplete/MassStorage/Lib/VirtualFAT.c b/Bootloaders/Incomplete/MassStorage/Lib/VirtualFAT.c index 7b0c5dda5..5d91cefaf 100644 --- a/Bootloaders/Incomplete/MassStorage/Lib/VirtualFAT.c +++ b/Bootloaders/Incomplete/MassStorage/Lib/VirtualFAT.c @@ -34,42 +34,65 @@ static const FATBootBlock_t BootBlock = { .Bootstrap = {0xEB, 0x3C, 0x90}, .Description = "mkdosfs", - .BlockSize = VIRTUAL_MEMORY_BLOCK_SIZE, - .BlocksPerAllocationUnit = ALLOCATION_UNIT_BLOCKS, - .ReservedBlocks = 1, + .SectorSize = SECTOR_SIZE_BYTES, + .SectorsPerCluster = SECTOR_PER_CLUSTER, + .ReservedSectors = 1, .FATCopies = 2, - .RootDirectoryEntries = 512, - .TotalBlocks16 = LUN_MEDIA_BLOCKS, + .RootDirectoryEntries = (SECTOR_SIZE_BYTES / sizeof(FATDirectoryEntry_t)), + .TotalSectors16 = LUN_MEDIA_BLOCKS, .MediaDescriptor = 0xF8, - .BlocksPerFAT = 1, - .BlocksPerTrack = 32, - .Heads = 64, - .HiddenBlocks = 0, - .TotalBlocks32 = 0, + .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 = "FAT16 ", + .FilesystemIdentifier = "FAT12 ", .BootstrapProgram = {0}, .MagicSignature = 0xAA55, }; static FATDirectoryEntry_t FirmwareFileEntry = { - .Filename = "Firmware", - .Extension = "bin", + .Filename = "FIRMWARE", + .Extension = "BIN", .Attributes = 0, .Reserved = {0}, - .CreationTime = (1 << 11) | (1 << 5), - .CreationDate = (9 << 9) | (2 << 5) | (14 << 0), - .StartingCluster = 4, - .FileSize = (FLASHEND + 1UL), + .CreationTime = FAT_TIME(1, 1, 0), + .CreationDate = FAT_DATE(14, 2, 1989), + .StartingCluster = 2, + .FileSizeBytes = FIRMWARE_FILE_SIZE, }; -static void WriteBlock(uint16_t BlockNumber) + +static void UpdateFAT12ClusterEntry(uint8_t* FATTable, + const uint16_t Index, + const uint16_t ChainEntry) +{ + /* Calculate the starting offset of the cluster entry in the FAT12 table */ + uint8_t FATOffset = (Index * 3) / 2; + bool UpperNibble = (((Index * 3) % 2) != 0); + + /* Check if the start of the entry is at an upper nibble of the byte, fill + * out FAT12 entry as required */ + if (UpperNibble) + { + FATTable[FATOffset] = (FATTable[FATOffset] & 0x0F) | ((ChainEntry & 0x0F) << 4); + FATTable[FATOffset + 1] = (ChainEntry >> 4); + } + else + { + FATTable[FATOffset] = ChainEntry; + FATTable[FATOffset + 1] = (FATTable[FATOffset] & 0xF0) | (ChainEntry >> 8); + } +} + +static void WriteBlock(const uint16_t BlockNumber) { - uint8_t BlockBuffer[512]; + uint8_t BlockBuffer[SECTOR_SIZE_BYTES]; /* Wait until endpoint is ready before continuing */ if (Endpoint_WaitUntilReady()) @@ -78,12 +101,40 @@ static void WriteBlock(uint16_t BlockNumber) Endpoint_Read_Stream_LE(BlockBuffer, sizeof(BlockBuffer), NULL); Endpoint_ClearOUT(); - // TODO: Write to FLASH + if ((BlockNumber >= 4) && (BlockNumber < (4 + (FIRMWARE_FILE_SIZE / SECTOR_SIZE_BYTES)))) + { + uint32_t WriteFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; + + for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i += 2) + { + /* Disallow writing to the bootloader section */ + if (WriteFlashAddress > BOOT_START_ADDR) + continue; + + if ((WriteFlashAddress % SPM_PAGESIZE) == 0) + { + /* Erase the given FLASH page, ready to be programmed */ + boot_page_erase(WriteFlashAddress); + boot_spm_busy_wait(); + } + + /* Write the next data word to the FLASH page */ + boot_page_fill(WriteFlashAddress, (BlockBuffer[i + 1] << 8) | BlockBuffer[i]); + WriteFlashAddress += 2; + + if ((WriteFlashAddress % SPM_PAGESIZE) == 0) + { + /* Write the filled FLASH page to memory */ + boot_page_write(WriteFlashAddress - SPM_PAGESIZE); + boot_spm_busy_wait(); + } + } + } } -static void ReadBlock(uint16_t BlockNumber) +static void ReadBlock(const uint16_t BlockNumber) { - uint8_t BlockBuffer[512]; + uint8_t BlockBuffer[SECTOR_SIZE_BYTES]; memset(BlockBuffer, 0x00, sizeof(BlockBuffer)); switch (BlockNumber) @@ -95,25 +146,17 @@ static void ReadBlock(uint16_t BlockNumber) case 1: case 2: /* Cluster 0: Media type/Reserved */ - ((uint16_t*)&BlockBuffer)[0] = 0xFF00 | BootBlock.MediaDescriptor; + UpdateFAT12ClusterEntry(BlockBuffer, 0, 0xF00 | BootBlock.MediaDescriptor); /* Cluster 1: Reserved */ - ((uint16_t*)&BlockBuffer)[1] = 0xFFFF; - - /* Cluster 2: Reserved */ - ((uint16_t*)&BlockBuffer)[2] = 0xFFFF; + UpdateFAT12ClusterEntry(BlockBuffer, 1, 0xFFF); - /* Cluster 3: FIRMWARE.BIN File Entry */ - ((uint16_t*)&BlockBuffer)[3] = 0xFFFF; - - /* Cluster 4 onwards: Cluster chain of FIRMWARE.BIN */ - for (uint16_t i = 0; i < ((FLASHEND + 1) / (VIRTUAL_MEMORY_BLOCK_SIZE * ALLOCATION_UNIT_BLOCKS)); i++) - { - ((uint16_t*)&BlockBuffer)[i + 4] = i + 5; - } + /* Cluster 2 onwards: Cluster chain of FIRMWARE.BIN */ + for (uint16_t i = 0; i < FILE_CLUSTERS(FIRMWARE_FILE_SIZE); i++) + UpdateFAT12ClusterEntry(BlockBuffer, i+2, i+3); /* Mark last cluster as end of file */ - ((uint16_t*)&BlockBuffer)[((FLASHEND + 1) / (VIRTUAL_MEMORY_BLOCK_SIZE * ALLOCATION_UNIT_BLOCKS)) + 4] = 0xFFFF; + UpdateFAT12ClusterEntry(BlockBuffer, FILE_CLUSTERS(FIRMWARE_FILE_SIZE) + 1, 0xFFF); break; case 3: @@ -121,6 +164,14 @@ static void ReadBlock(uint16_t BlockNumber) break; default: + if ((BlockNumber >= 4) && (BlockNumber < (4 + (FIRMWARE_FILE_SIZE / SECTOR_SIZE_BYTES)))) + { + uint32_t ReadFlashAddress = (uint32_t)(BlockNumber - 4) * SECTOR_SIZE_BYTES; + + for (uint16_t i = 0; i < SECTOR_SIZE_BYTES; i++) + BlockBuffer[i] = pgm_read_byte_far(ReadFlashAddress++); + } + break; } @@ -138,6 +189,8 @@ void VirtualFAT_WriteBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, { uint16_t CurrentBlock = (uint16_t)BlockAddress; + /* Emulated FAT is performed per-block, pass each requested block index + * to the emulation function */ while (TotalBlocks--) WriteBlock(CurrentBlock++); } @@ -148,6 +201,8 @@ void VirtualFAT_ReadBlocks(USB_ClassInfo_MS_Device_t* const MSInterfaceInfo, { uint16_t CurrentBlock = (uint16_t)BlockAddress; + /* Emulated FAT is performed per-block, pass each requested block index + * to the emulation function */ while (TotalBlocks--) ReadBlock(CurrentBlock++); }