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_settings.h" | ||||||
| #include "bootloader.h" | #include "bootloader.h" | ||||||
|  |  | ||||||
|  | // #define CREATE_MANY_FILES | ||||||
|  |  | ||||||
|  |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint8_t JumpInstruction[3]; |     uint8_t JumpInstruction[3]; | ||||||
| @@ -48,7 +50,6 @@ typedef struct { | |||||||
|     uint16_t startCluster; |     uint16_t startCluster; | ||||||
|     uint32_t size; |     uint32_t size; | ||||||
| } __attribute__((packed)) DirEntry; | } __attribute__((packed)) DirEntry; | ||||||
|  |  | ||||||
| STATIC_ASSERT(sizeof(DirEntry) == 32); | STATIC_ASSERT(sizeof(DirEntry) == 32); | ||||||
|  |  | ||||||
| struct TextFile { | struct TextFile { | ||||||
| @@ -78,9 +79,56 @@ const char indexFile[] = // | |||||||
|     "</body>" |     "</body>" | ||||||
|     "</html>\n"; |     "</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[] = { | static struct TextFile const info[] = { | ||||||
|     {.name = "INFO_UF2TXT", .content = infoUf2File}, |     {.name = "INFO_UF2TXT", .content = infoUf2File}, | ||||||
|     {.name = "INDEX   HTM", .content = indexFile}, |     {.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"}, |     {.name = "CURRENT UF2"}, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| @@ -110,8 +158,9 @@ STATIC_ASSERT(ARRAY_SIZE2(indexFile) < 512); | |||||||
|  |  | ||||||
| // all directory entries must fit in a single sector | // all directory entries must fit in a single sector | ||||||
| // because otherwise current code overflows buffer | // because otherwise current code overflows buffer | ||||||
| STATIC_ASSERT(NUM_DIRENTRIES < (512 / sizeof(DirEntry))); | #define DIRENTRIES_PER_SECTOR (512/sizeof(DirEntry)) | ||||||
| // STATIC_ASSERT(NUM_DIRENTRIES < (512 / sizeof(DirEntry)) * ROOT_DIR_SECTORS); |  | ||||||
|  | STATIC_ASSERT(NUM_DIRENTRIES < DIRENTRIES_PER_SECTOR * ROOT_DIR_SECTORS); | ||||||
|  |  | ||||||
|  |  | ||||||
| static FAT_BootBlock const BootBlock = { | static FAT_BootBlock const BootBlock = { | ||||||
| @@ -121,7 +170,7 @@ static FAT_BootBlock const BootBlock = { | |||||||
|     .SectorsPerCluster    = 1, |     .SectorsPerCluster    = 1, | ||||||
|     .ReservedSectors      = RESERVED_SECTORS, |     .ReservedSectors      = RESERVED_SECTORS, | ||||||
|     .FATCopies            = 2, |     .FATCopies            = 2, | ||||||
|     .RootDirectoryEntries = (ROOT_DIR_SECTORS * 512 / 32), |     .RootDirectoryEntries = (ROOT_DIR_SECTORS * DIRENTRIES_PER_SECTOR), | ||||||
|     .TotalSectors16       = NUM_FAT_BLOCKS - 2, |     .TotalSectors16       = NUM_FAT_BLOCKS - 2, | ||||||
|     .MediaDescriptor      = 0xF8, |     .MediaDescriptor      = 0xF8, | ||||||
|     .SectorsPerFAT        = SECTORS_PER_FAT, |     .SectorsPerFAT        = SECTORS_PER_FAT, | ||||||
| @@ -205,8 +254,11 @@ void read_block(uint32_t block_no, uint8_t *data) { | |||||||
|             sectionIdx -= SECTORS_PER_FAT; |             sectionIdx -= SECTORS_PER_FAT; | ||||||
|         if (sectionIdx == 0) { |         if (sectionIdx == 0) { | ||||||
|             data[0] = 0xf0; |             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) { |             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) { |         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; |                 ((uint16_t *)(void *)data)[i] = v == UF2_LAST_SECTOR ? 0xffff : v + 1; | ||||||
|         } |         } | ||||||
|     } else if (block_no < START_CLUSTERS) { |     } else if (block_no < START_CLUSTERS) { | ||||||
|         // Use STATIC_ASSERT() above to ensure only first sector has entries |  | ||||||
|         sectionIdx -= START_ROOTDIR; |         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); |             padded_memcpy(d->name, (char const *) BootBlock.VolumeLabel, 11); | ||||||
|             d->attrs = 0x28; |             d->attrs = 0x28; | ||||||
|             for (int i = 0; i < NUM_FILES; ++i) { |             remainingEntries--; | ||||||
|                 d++; |         } | ||||||
|  |  | ||||||
|  |         for (int i = DIRENTRIES_PER_SECTOR * sectionIdx; | ||||||
|  |              remainingEntries > 0 && i < NUM_FILES; | ||||||
|  |              i++, d++) { | ||||||
|             struct TextFile const * inf = &info[i]; |             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->size = inf->content ? strlen(inf->content) : UF2_SIZE; | ||||||
|             d->startCluster = i + 2; |             d->startCluster = i + 2; | ||||||
|             padded_memcpy(d->name, inf->name, 11); |             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 { |     } else { | ||||||
|         sectionIdx -= START_CLUSTERS; |         sectionIdx -= START_CLUSTERS; | ||||||
|         if (sectionIdx < NUM_FILES - 1) { |         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 | #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