Raises file limit from 14 to 62 files.
Enable all four sectors of root directory to contain files.
This commit is contained in:
		@@ -9,6 +9,8 @@
 | 
			
		||||
#include "bootloader_settings.h"
 | 
			
		||||
#include "bootloader.h"
 | 
			
		||||
 | 
			
		||||
// #define CREATE_MANY_FILES
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    uint8_t JumpInstruction[3];
 | 
			
		||||
@@ -48,7 +50,6 @@ typedef struct {
 | 
			
		||||
    uint16_t startCluster;
 | 
			
		||||
    uint32_t size;
 | 
			
		||||
} __attribute__((packed)) DirEntry;
 | 
			
		||||
 | 
			
		||||
STATIC_ASSERT(sizeof(DirEntry) == 32);
 | 
			
		||||
 | 
			
		||||
struct TextFile {
 | 
			
		||||
@@ -78,9 +79,56 @@ const char indexFile[] = //
 | 
			
		||||
    "</body>"
 | 
			
		||||
    "</html>\n";
 | 
			
		||||
 | 
			
		||||
#ifdef CREATE_MANY_FILES
 | 
			
		||||
const char dataFile00[] = "This is the data for File 00\r\n";
 | 
			
		||||
const char dataFile01[] = "This is the data for File 01\r\n";
 | 
			
		||||
const char dataFile02[] = "This is the data for File 02\r\n";
 | 
			
		||||
const char dataFile03[] = "This is the data for File 03\r\n";
 | 
			
		||||
const char dataFile04[] = "This is the data for File 04\r\n";
 | 
			
		||||
const char dataFile05[] = "This is the data for File 05\r\n";
 | 
			
		||||
const char dataFile06[] = "This is the data for File 06\r\n";
 | 
			
		||||
const char dataFile07[] = "This is the data for File 07\r\n";
 | 
			
		||||
const char dataFile08[] = "This is the data for File 08\r\n";
 | 
			
		||||
const char dataFile09[] = "This is the data for File 09\r\n";
 | 
			
		||||
const char dataFile10[] = "This is the data for File 10\r\n";
 | 
			
		||||
const char dataFile11[] = "This is the data for File 11\r\n";
 | 
			
		||||
const char dataFile12[] = "This is the data for File 12\r\n";
 | 
			
		||||
const char dataFile13[] = "This is the data for File 13\r\n";
 | 
			
		||||
const char dataFile14[] = "This is the data for File 14\r\n";
 | 
			
		||||
const char dataFile15[] = "This is the data for File 15\r\n";
 | 
			
		||||
const char dataFile16[] = "This is the data for File 16\r\n";
 | 
			
		||||
const char dataFile17[] = "This is the data for File 17\r\n";
 | 
			
		||||
const char dataFile18[] = "This is the data for File 18\r\n";
 | 
			
		||||
const char dataFile19[] = "This is the data for File 19\r\n";
 | 
			
		||||
#endif // CREATE_MANY_FILES
 | 
			
		||||
 | 
			
		||||
// WARNING -- code presumes only one NULL .content for .UF2 file
 | 
			
		||||
//            and requires it be the last element of the array
 | 
			
		||||
static struct TextFile const info[] = {
 | 
			
		||||
    {.name = "INFO_UF2TXT", .content = infoUf2File},
 | 
			
		||||
    {.name = "INDEX   HTM", .content = indexFile},
 | 
			
		||||
#ifdef CREATE_MANY_FILES
 | 
			
		||||
    {.name = "FILE00  TXT", .content = dataFile00},
 | 
			
		||||
    {.name = "FILE01  TXT", .content = dataFile01},
 | 
			
		||||
    {.name = "FILE02  TXT", .content = dataFile02},
 | 
			
		||||
    {.name = "FILE03  TXT", .content = dataFile03},
 | 
			
		||||
    {.name = "FILE04  TXT", .content = dataFile04},
 | 
			
		||||
    {.name = "FILE05  TXT", .content = dataFile05},
 | 
			
		||||
    {.name = "FILE06  TXT", .content = dataFile06},
 | 
			
		||||
    {.name = "FILE07  TXT", .content = dataFile07},
 | 
			
		||||
    {.name = "FILE08  TXT", .content = dataFile08},
 | 
			
		||||
    {.name = "FILE09  TXT", .content = dataFile09},
 | 
			
		||||
    {.name = "FILE10  TXT", .content = dataFile10},
 | 
			
		||||
    {.name = "FILE11  TXT", .content = dataFile11},
 | 
			
		||||
    {.name = "FILE12  TXT", .content = dataFile12},
 | 
			
		||||
    {.name = "FILE13  TXT", .content = dataFile13},
 | 
			
		||||
    {.name = "FILE14  TXT", .content = dataFile14},
 | 
			
		||||
    {.name = "FILE15  TXT", .content = dataFile15},
 | 
			
		||||
    {.name = "FILE16  TXT", .content = dataFile16},
 | 
			
		||||
    {.name = "FILE17  TXT", .content = dataFile17},
 | 
			
		||||
    {.name = "FILE18  TXT", .content = dataFile18},
 | 
			
		||||
    {.name = "FILE19  TXT", .content = dataFile19},
 | 
			
		||||
#endif
 | 
			
		||||
    {.name = "CURRENT UF2"},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -110,8 +158,9 @@ STATIC_ASSERT(ARRAY_SIZE2(indexFile) < 512);
 | 
			
		||||
 | 
			
		||||
// all directory entries must fit in a single sector
 | 
			
		||||
// because otherwise current code overflows buffer
 | 
			
		||||
STATIC_ASSERT(NUM_DIRENTRIES < (512 / sizeof(DirEntry)));
 | 
			
		||||
// STATIC_ASSERT(NUM_DIRENTRIES < (512 / sizeof(DirEntry)) * ROOT_DIR_SECTORS);
 | 
			
		||||
#define DIRENTRIES_PER_SECTOR (512/sizeof(DirEntry))
 | 
			
		||||
 | 
			
		||||
STATIC_ASSERT(NUM_DIRENTRIES < DIRENTRIES_PER_SECTOR * ROOT_DIR_SECTORS);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static FAT_BootBlock const BootBlock = {
 | 
			
		||||
@@ -121,7 +170,7 @@ static FAT_BootBlock const BootBlock = {
 | 
			
		||||
    .SectorsPerCluster    = 1,
 | 
			
		||||
    .ReservedSectors      = RESERVED_SECTORS,
 | 
			
		||||
    .FATCopies            = 2,
 | 
			
		||||
    .RootDirectoryEntries = (ROOT_DIR_SECTORS * 512 / 32),
 | 
			
		||||
    .RootDirectoryEntries = (ROOT_DIR_SECTORS * DIRENTRIES_PER_SECTOR),
 | 
			
		||||
    .TotalSectors16       = NUM_FAT_BLOCKS - 2,
 | 
			
		||||
    .MediaDescriptor      = 0xF8,
 | 
			
		||||
    .SectorsPerFAT        = SECTORS_PER_FAT,
 | 
			
		||||
@@ -205,8 +254,11 @@ void read_block(uint32_t block_no, uint8_t *data) {
 | 
			
		||||
            sectionIdx -= SECTORS_PER_FAT;
 | 
			
		||||
        if (sectionIdx == 0) {
 | 
			
		||||
            data[0] = 0xf0;
 | 
			
		||||
            // WARNING -- code presumes only one NULL .content for .UF2 file
 | 
			
		||||
            //            and all non-NULL .content fit in one sector
 | 
			
		||||
            //            and requires it be the last element of the array
 | 
			
		||||
            for (int i = 1; i < NUM_FILES * 2 + 4; ++i) {
 | 
			
		||||
                data[i] = 0xff; // WARNING -- code presumes each non-UF2 file content fits in single sector
 | 
			
		||||
                data[i] = 0xff;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (int i = 0; i < 256; ++i) {
 | 
			
		||||
@@ -215,20 +267,33 @@ void read_block(uint32_t block_no, uint8_t *data) {
 | 
			
		||||
                ((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1;
 | 
			
		||||
        }
 | 
			
		||||
    } else if (block_no < START_CLUSTERS) {
 | 
			
		||||
        // Use STATIC_ASSERT() above to ensure only first sector has entries
 | 
			
		||||
 | 
			
		||||
        sectionIdx -= START_ROOTDIR;
 | 
			
		||||
        if (sectionIdx == 0) {
 | 
			
		||||
            DirEntry *d = (void *)data;
 | 
			
		||||
 | 
			
		||||
        DirEntry *d = (void *)data;
 | 
			
		||||
        int remainingEntries = DIRENTRIES_PER_SECTOR;
 | 
			
		||||
        if (sectionIdx == 0) { // volume label first
 | 
			
		||||
            // volume label is first directory entry
 | 
			
		||||
            padded_memcpy(d->name, (char const *) BootBlock.VolumeLabel, 11);
 | 
			
		||||
            d->attrs = 0x28;
 | 
			
		||||
            for (int i = 0; i < NUM_FILES; ++i) {
 | 
			
		||||
                d++;
 | 
			
		||||
                struct TextFile const *inf = &info[i];
 | 
			
		||||
                d->size = inf->content ? strlen(inf->content) : UF2_SIZE;
 | 
			
		||||
                d->startCluster = i + 2;
 | 
			
		||||
                padded_memcpy(d->name, inf->name, 11);
 | 
			
		||||
            }
 | 
			
		||||
            remainingEntries--;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (int i = DIRENTRIES_PER_SECTOR * sectionIdx;
 | 
			
		||||
             remainingEntries > 0 && i < NUM_FILES;
 | 
			
		||||
             i++, d++) {
 | 
			
		||||
            struct TextFile const * inf = &info[i];
 | 
			
		||||
            // WARNING -- code presumes only one NULL .content for .UF2 file
 | 
			
		||||
            //            and requires it be the last element of the array
 | 
			
		||||
            d->size = inf->content ? strlen(inf->content) : UF2_SIZE;
 | 
			
		||||
            d->startCluster = i + 2;
 | 
			
		||||
            padded_memcpy(d->name, inf->name, 11);
 | 
			
		||||
            // DIR_WrtTime and DIR_WrtDate must be supported
 | 
			
		||||
            d->updateDate     = __DOSDATE__;
 | 
			
		||||
            d->lastAccessDate = __DOSDATE__;
 | 
			
		||||
            d->createDate     = __DOSDATE__;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    } else {
 | 
			
		||||
        sectionIdx -= START_CLUSTERS;
 | 
			
		||||
        if (sectionIdx < NUM_FILES - 1) {
 | 
			
		||||
 
 | 
			
		||||
@@ -296,3 +296,38 @@ static inline void check_uf2_handover(uint8_t *buffer, uint32_t blocks_remaining
 | 
			
		||||
#endif // ARRAYSIZE2_H
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef COMPILE_DATE_H
 | 
			
		||||
#define COMPILE_DATE_H
 | 
			
		||||
 | 
			
		||||
#define __YEAR_INT__ ((( \
 | 
			
		||||
  (__DATE__ [ 7u] - '0')  * 10u + \
 | 
			
		||||
  (__DATE__ [ 8u] - '0')) * 10u + \
 | 
			
		||||
  (__DATE__ [ 9u] - '0')) * 10u + \
 | 
			
		||||
  (__DATE__ [10u] - '0'))
 | 
			
		||||
 | 
			
		||||
#define __MONTH_INT__ ( \
 | 
			
		||||
  (__DATE__ [2u] == 'n' && __DATE__ [1u] == 'a') ?  1u  /*Jan*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'b'                        ) ?  2u  /*Feb*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'r' && __DATE__ [1u] == 'a') ?  3u  /*Mar*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'r'                        ) ?  4u  /*Apr*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'y'                        ) ?  5u  /*May*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'n'                        ) ?  6u  /*Jun*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'l'                        ) ?  7u  /*Jul*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'g'                        ) ?  8u  /*Jul*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'p'                        ) ?  9u  /*Jul*/ \
 | 
			
		||||
: (__DATE__ [2u] == 't'                        ) ? 10u  /*Jul*/ \
 | 
			
		||||
: (__DATE__ [2u] == 'v'                        ) ? 11u  /*Jul*/ \
 | 
			
		||||
:                                                  12u  /*Dec*/ )
 | 
			
		||||
 | 
			
		||||
#define __DAY_INT__ ( \
 | 
			
		||||
   (__DATE__ [4u] == ' ' ? 0u : __DATE__ [4u] - '0') * 10u \
 | 
			
		||||
 + (__DATE__ [5u] - '0')                                   )
 | 
			
		||||
 | 
			
		||||
#define __DOSDATE__ ( \
 | 
			
		||||
	((__YEAR_INT__  - 1980u) << 9u) | \
 | 
			
		||||
	( __MONTH_INT__          << 5u) | \
 | 
			
		||||
                    ( __DAY_INT__            << 0u) )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // COMPILE_DATE_H
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user