BRFS.C 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Test implementation of Bart's RAM File System (BRFS)
  2. /*
  3. General Idea:
  4. - HDD for the average home user was <100MB until after 1990
  5. - SPI NOR Flash provides around the same amount of storage, with relatively little wear
  6. - However, writes are extremely slow
  7. - FPGC has 64MiB RAM, which is a lot even for 64 bit addressable words
  8. - 32MiB is already more than enough for the FPGC in its current form
  9. - Use the other 32MiB as a fully in RAM filesystem
  10. - That initializes from SPI flash and writes back to Flash at a chosen time
  11. */
  12. /*
  13. Implementation Idea:
  14. - Use superblock for info/addresses, no hard-coded sizes!
  15. - Allows for different storage media, easier testing on tiny size, and more future proof
  16. */
  17. /*
  18. Implementation Details:
  19. --------------------------------------------------
  20. | superblock | FAT | Data+Dir blocks (same size) |
  21. --------------------------------------------------
  22. 16 word superblock:
  23. - (1) total blocks
  24. - (1) bytes per block
  25. - (10) label [1 char per word]
  26. - (1) brfs version
  27. - (3) reserved
  28. 8 word Dir entries:
  29. - (4) filename.ext [4 chars per word]
  30. - (1) modify date [to be implemented when RTC]
  31. - (1) flags [max 32 flags, TBD]
  32. - (1) 1st FAT idx
  33. - (1) file size [in words, not bytes]
  34. */
  35. #define word char
  36. #include "LIB/MATH.C"
  37. #include "LIB/SYS.C"
  38. #include "LIB/STDLIB.C"
  39. #define BRFS_RAM_STORAGE_ADDR 0x500000
  40. #define SUPERBLOCK_SIZE 16
  41. word *brfs_ram_storage = (word*) BRFS_RAM_STORAGE_ADDR; // RAM storage of file system
  42. // 16 words long
  43. struct brfs_superblock
  44. {
  45. word total_blocks;
  46. word bytes_per_block;
  47. word label[10]; // 1 char per word
  48. word brfs_version;
  49. word reserved[3];
  50. };
  51. // 16 words long
  52. struct brfs_dir_entry
  53. {
  54. word filename[4]; // 4 chars per word
  55. word modify_date; // TBD when RTC added to FPGC
  56. word flags;
  57. word fat_idx; // idx of first FAT block
  58. word filesize; // file size in words, not bytes
  59. };
  60. // Creates hexdump like dump
  61. void brfs_dump_section(word* addr, word len, word linesize)
  62. {
  63. char buf[16];
  64. word i;
  65. for (i = 0; i < len; i++)
  66. {
  67. itoah(addr[i], buf);
  68. if (strlen(buf+2) == 1)
  69. uprintc('0');
  70. uprint(buf+2);
  71. uprintc(' ');
  72. // newline every linesize words
  73. // also print last linesize words as chars if alphanum
  74. if (i != 0 && MATH_modU(i+1, linesize) == 0)
  75. {
  76. uprint(" ");
  77. word j;
  78. for (j = i - (linesize-1); j < i+1; j++)
  79. {
  80. if (isalnum(addr[j]) || addr[j] == ' ')
  81. uprintc(addr[j]);
  82. else
  83. uprintc('.');
  84. }
  85. uprintc('\n');
  86. }
  87. }
  88. }
  89. void brfs_dump(word* ram_addr, word fatsize, word datasize)
  90. {
  91. // Superblock dump
  92. uprintln("Superblock:");
  93. brfs_dump_section(ram_addr, SUPERBLOCK_SIZE, 16);
  94. // FAT dump
  95. uprintln("\nFAT:");
  96. brfs_dump_section(ram_addr+SUPERBLOCK_SIZE, fatsize, 8);
  97. // Datablock dump
  98. uprintln("\nData:");
  99. brfs_dump_section(ram_addr+SUPERBLOCK_SIZE+fatsize, datasize, 16);
  100. uprintc('\n');
  101. }
  102. void brfs_format(word* ram_addr, word blocks, word bytes_per_block, char* label, word full_format)
  103. {
  104. // Create a superblock
  105. struct brfs_superblock superblock;
  106. // Initialize to 0
  107. memset(&superblock, 0, sizeof(superblock));
  108. // Set values of superblock
  109. superblock.total_blocks = blocks;
  110. superblock.bytes_per_block = bytes_per_block;
  111. strcpy(&(superblock.label), label);
  112. superblock.brfs_version = 1;
  113. // Copy superblock to head of ram addr
  114. memcpy(ram_addr, &superblock, sizeof(superblock));
  115. // Create FAT
  116. memset(ram_addr + SUPERBLOCK_SIZE, 0, blocks);
  117. // Create Data section
  118. if (full_format)
  119. {
  120. memset(ram_addr + SUPERBLOCK_SIZE + blocks, 0, blocks * bytes_per_block);
  121. }
  122. // Create root dir entry in first block
  123. struct brfs_dir_entry root_dir;
  124. // Initialize to 0
  125. memset(&root_dir, 0, sizeof(root_dir));
  126. // Copy root dir entry to first block
  127. memcpy(ram_addr + SUPERBLOCK_SIZE + blocks, &root_dir, sizeof(root_dir));
  128. }
  129. int main()
  130. {
  131. // Clear UART screen:
  132. uprintc(0x1B);
  133. uprintc(0x5B);
  134. uprintc(0x32);
  135. uprintc(0x4A);
  136. uprintln("------------------------");
  137. uprintln("BRFS test implementation");
  138. uprintln("------------------------");
  139. word blocks = 8;
  140. word bytes_per_block = 16;
  141. word full_format = 1;
  142. brfs_format(brfs_ram_storage, blocks, bytes_per_block, "Label", full_format);
  143. brfs_dump(brfs_ram_storage, blocks, blocks*bytes_per_block);
  144. return 'q';
  145. }
  146. void interrupt()
  147. {
  148. // handle all interrupts
  149. word i = getIntID();
  150. switch(i)
  151. {
  152. case INTID_TIMER1:
  153. timer1Value = 1; // notify ending of timer1
  154. break;
  155. case INTID_TIMER2:
  156. break;
  157. case INTID_UART0:
  158. break;
  159. case INTID_GPU:
  160. break;
  161. case INTID_TIMER3:
  162. break;
  163. case INTID_PS2:
  164. break;
  165. case INTID_UART1:
  166. break;
  167. case INTID_UART2:
  168. break;
  169. }
  170. }