123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // Test implementation of Bart's RAM File System (BRFS)
- /*
- General Idea:
- - HDD for the average home user was <100MB until after 1990
- - SPI NOR Flash provides around the same amount of storage, with relatively little wear
- - However, writes are extremely slow
- - FPGC has 64MiB RAM, which is a lot even for 64 bit addressable words
- - 32MiB is already more than enough for the FPGC in its current form
- - Use the other 32MiB as a fully in RAM filesystem
- - That initializes from SPI flash and writes back to Flash at a chosen time
- */
- /*
- Implementation Idea:
- - Use superblock for info/addresses, no hard-coded sizes!
- - Allows for different storage media, easier testing on tiny size, and more future proof
- */
- /*
- Implementation Details:
- --------------------------------------------------
- | superblock | FAT | Data+Dir blocks (same size) |
- --------------------------------------------------
- 16 word superblock:
- - (1) total blocks
- - (1) bytes per block
- - (10) label [1 char per word]
- - (1) brfs version
- - (3) reserved
- 8 word Dir entries:
- - (4) filename.ext [4 chars per word]
- - (1) modify date [to be implemented when RTC]
- - (1) flags [max 32 flags, TBD]
- - (1) 1st FAT idx
- - (1) file size [in words, not bytes]
- */
- #define word char
- #include "LIB/MATH.C"
- #include "LIB/SYS.C"
- #include "LIB/STDLIB.C"
- #define BRFS_RAM_STORAGE_ADDR 0x500000
- #define SUPERBLOCK_SIZE 16
- word *brfs_ram_storage = (word*) BRFS_RAM_STORAGE_ADDR; // RAM storage of file system
- // 16 words long
- struct brfs_superblock
- {
- word total_blocks;
- word bytes_per_block;
- word label[10]; // 1 char per word
- word brfs_version;
- word reserved[3];
- };
- // 16 words long
- struct brfs_dir_entry
- {
- word filename[4]; // 4 chars per word
- word modify_date; // TBD when RTC added to FPGC
- word flags;
- word fat_idx; // idx of first FAT block
- word filesize; // file size in words, not bytes
- };
- // Creates hexdump like dump
- void brfs_dump_section(word* addr, word len, word linesize)
- {
- char buf[16];
- word i;
- for (i = 0; i < len; i++)
- {
- itoah(addr[i], buf);
- if (strlen(buf+2) == 1)
- uprintc('0');
- uprint(buf+2);
- uprintc(' ');
- // newline every linesize words
- // also print last linesize words as chars if alphanum
- if (i != 0 && MATH_modU(i+1, linesize) == 0)
- {
- uprint(" ");
- word j;
- for (j = i - (linesize-1); j < i+1; j++)
- {
- if (isalnum(addr[j]) || addr[j] == ' ')
- uprintc(addr[j]);
- else
- uprintc('.');
- }
- uprintc('\n');
- }
- }
- }
- void brfs_dump(word* ram_addr, word fatsize, word datasize)
- {
- // Superblock dump
- uprintln("Superblock:");
- brfs_dump_section(ram_addr, SUPERBLOCK_SIZE, 16);
- // FAT dump
- uprintln("\nFAT:");
- brfs_dump_section(ram_addr+SUPERBLOCK_SIZE, fatsize, 8);
- // Datablock dump
- uprintln("\nData:");
- brfs_dump_section(ram_addr+SUPERBLOCK_SIZE+fatsize, datasize, 16);
- uprintc('\n');
- }
- void brfs_format(word* ram_addr, word blocks, word bytes_per_block, char* label, word full_format)
- {
- // Create a superblock
- struct brfs_superblock superblock;
- // Initialize to 0
- memset(&superblock, 0, sizeof(superblock));
- // Set values of superblock
- superblock.total_blocks = blocks;
- superblock.bytes_per_block = bytes_per_block;
- strcpy(&(superblock.label), label);
- superblock.brfs_version = 1;
- // Copy superblock to head of ram addr
- memcpy(ram_addr, &superblock, sizeof(superblock));
- // Create FAT
- memset(ram_addr + SUPERBLOCK_SIZE, 0, blocks);
- // Create Data section
- if (full_format)
- {
- memset(ram_addr + SUPERBLOCK_SIZE + blocks, 0, blocks * bytes_per_block);
- }
-
- // Create root dir entry in first block
- struct brfs_dir_entry root_dir;
- // Initialize to 0
- memset(&root_dir, 0, sizeof(root_dir));
- // Copy root dir entry to first block
- memcpy(ram_addr + SUPERBLOCK_SIZE + blocks, &root_dir, sizeof(root_dir));
-
- }
- int main()
- {
- // Clear UART screen:
- uprintc(0x1B);
- uprintc(0x5B);
- uprintc(0x32);
- uprintc(0x4A);
- uprintln("------------------------");
- uprintln("BRFS test implementation");
- uprintln("------------------------");
- word blocks = 8;
- word bytes_per_block = 16;
- word full_format = 1;
- brfs_format(brfs_ram_storage, blocks, bytes_per_block, "Label", full_format);
- brfs_dump(brfs_ram_storage, blocks, blocks*bytes_per_block);
- return 'q';
- }
- void interrupt()
- {
- // handle all interrupts
- word i = getIntID();
- switch(i)
- {
- case INTID_TIMER1:
- timer1Value = 1; // notify ending of timer1
- break;
- case INTID_TIMER2:
- break;
- case INTID_UART0:
- break;
- case INTID_GPU:
- break;
- case INTID_TIMER3:
- break;
- case INTID_PS2:
- break;
- case INTID_UART1:
- break;
- case INTID_UART2:
- break;
- }
- }
|