소스 검색

Added sync to flash syscall, fixed many bugs, added format cmd to shell, created checksum program, started on rm program, improved mkdir, added brfs user lib for struct defs.

bart 7 달 전
부모
커밋
6a15b3499f
10개의 변경된 파일280개의 추가작업 그리고 78개의 파일을 삭제
  1. 6 5
      BCC/BDOS/BDOS.c
  2. 19 37
      BCC/BDOS/lib/brfs.c
  3. 44 20
      BCC/BDOS/lib/shell.c
  4. 2 2
      BCC/BDOS/lib/stdlib.c
  5. 91 0
      BCC/userBDOS/checksum.c
  6. 12 0
      BCC/userBDOS/lib/brfs.c
  7. 22 6
      BCC/userBDOS/lib/sys.c
  8. 6 7
      BCC/userBDOS/mkdir.c
  9. 76 0
      BCC/userBDOS/rm.c
  10. 2 1
      Documentation/docs/Software/BDOS/syscalls.md

+ 6 - 5
BCC/BDOS/BDOS.c

@@ -58,6 +58,7 @@
 #define SYS_FS_STAT 14
 #define SYS_FS_READDIR 15
 #define SYS_FS_GETCWD 16
+#define SYS_FS_SYNCFLASH 17
 // Syscalls 17-19 are reserved for future use
 #define SYS_SHELL_ARGC 20
 #define SYS_SHELL_ARGV 21
@@ -210,8 +211,6 @@ int main()
  * System calls
 */
 
-
-
 // System call handler
 // Returns at the same address it reads the command from
 void syscall()
@@ -280,14 +279,16 @@ void syscall()
     syscall_data[0] = 0; // TODO: implement
     break;
   case SYS_FS_GETCWD:
-    strcpy(syscall_data[0], shell_path);
+    strcpy(syscall_data, shell_path);
+    break;
+  case SYS_FS_SYNCFLASH:
+    brfs_write_to_flash();
     break;
   case SYS_SHELL_ARGC:
     syscall_data[0] = shell_num_tokens;
     break;
   case SYS_SHELL_ARGV:
-    // Not so fancy as we return by reference instead of making a copy
-    syscall_data[0] = shell_tokens;
+    memcpy(syscall_data, shell_tokens, sizeof(shell_tokens));
     break;
   case SYS_USB_KB_BUF:
     syscall_data[0] = USBkeyboard_buffer_parsed;

+ 19 - 37
BCC/BDOS/lib/brfs.c

@@ -175,7 +175,7 @@ word brfs_get_fat_idx_of_dir(char* dir_path)
       struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
       if (dir_entry->filename[0] != 0)
       {
-        char decompressed_filename[16];
+        char decompressed_filename[17];
         strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
         // Also check for directory flag
         if (strcmp(decompressed_filename, token) == 0 && dir_entry->flags == 1)
@@ -286,6 +286,13 @@ void brfs_create_single_dir_entry(struct brfs_dir_entry* dir_entry, char* filena
 */
 void brfs_init_directory(word* dir_addr, word dir_entries_max, word dir_fat_idx, word parent_fat_idx)
 {
+  // Get block size from superblock
+  struct brfs_superblock* superblock = (struct brfs_superblock*) brfs_ram_storage;
+  word block_size = superblock->words_per_block;
+
+  // Set data block of dir_fat_idx to 0
+  memset(dir_addr, 0, block_size);
+
   // Create . entry
   struct brfs_dir_entry dir_entry;
   brfs_create_single_dir_entry(&dir_entry, ".", dir_fat_idx, dir_entries_max*sizeof(struct brfs_dir_entry), 1);
@@ -404,7 +411,7 @@ word brfs_create_directory(char* parent_dir_path, char* dirname)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (parent_dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       if (strcmp(decompressed_filename, dirname) == 0)
       {
@@ -428,7 +435,7 @@ word brfs_create_directory(char* parent_dir_path, char* dirname)
 
   // Create dir entry
   struct brfs_dir_entry new_entry;
-  brfs_create_single_dir_entry(&new_entry, dirname, next_free_block, 0, 1);
+  brfs_create_single_dir_entry(&new_entry, dirname, next_free_block, dir_entries_max*sizeof(struct brfs_dir_entry), 1);
 
   // Copy dir entry to first free dir entry
   memcpy(
@@ -447,6 +454,7 @@ word brfs_create_directory(char* parent_dir_path, char* dirname)
 
   // Update changed block
   brfs_changed_blocks[next_free_block >> 5] |= (1 << (next_free_block & 31));
+  brfs_changed_blocks[parent_dir_fat_idx >> 5] |= (1 << (parent_dir_fat_idx & 31));
 
   return 1;
 }
@@ -490,7 +498,7 @@ word brfs_create_file(char* parent_dir_path, char* filename)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (parent_dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       if (strcmp(decompressed_filename, filename) == 0)
       {
@@ -570,7 +578,7 @@ void brfs_list_directory(char* dir_path)
     if (dir_entry->filename[0] != 0)
     {
       uprint("Filename: ");
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       uprint(decompressed_filename);
       uprint(" FAT idx: ");
@@ -619,7 +627,7 @@ word brfs_open_file(char* file_path)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       // Also check for directory flag to be 0
       if (strcmp(decompressed_filename, file_path_basename) == 0 && dir_entry->flags == 0)
@@ -693,7 +701,6 @@ word brfs_close_file(word file_pointer)
   return 0;
 }
 
-
 /**
  * Delete a file by removing all FAT blocks and the directory entry
  * Returns 1 on success, 0 on error
@@ -727,10 +734,10 @@ word brfs_delete_file(char* file_path)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       // Also check for directory flag to be 0
-      if (strcmp(decompressed_filename, file_path_basename) == 0 && dir_entry->flags == 0)
+      if (strcmp(decompressed_filename, file_path_basename) == 0 && (dir_entry->flags & 0x01) == 0)
       {
         // Found file
         // Check if file is already open
@@ -1083,7 +1090,7 @@ struct brfs_dir_entry* brfs_stat(char* file_path)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       // Also check for directory flag to be 0
       if (strcmp(decompressed_filename, file_path_basename) == 0)
@@ -1308,33 +1315,6 @@ void brfs_write_blocks_to_flash()
     brfs_write_sector_to_flash(sector_to_erase);
   }
 
-  // Write each block to flash in parts of 64 words
-  /*
-  for (i = 0; i < superblock->total_blocks; i++)
-  {
-    if (brfs_changed_blocks[i >> 5] & (1 << (i & 31)))
-    {
-      word j;
-      for (j = 0; j < superblock->words_per_block; j+=64)
-      {
-        word spiflash_addr = BRFS_SPIFLASH_BLOCK_ADDR; // Workaround because of large static number
-        spiflash_addr += i * (superblock->words_per_block * 4) + (j * 4);
-
-        word* data_addr = data_block_addr + (i * superblock->words_per_block) + j;
-        spiflash_write_page_in_words(data_addr, spiflash_addr, 64);
-
-        uprint("Wrote block ");
-        uprintDec(i);
-        uprint(" from RAM addr ");
-        uprintHex((word)data_addr);
-        uprint(" to SPI Flash addr ");
-        uprintHex(spiflash_addr);
-        uprintln("");
-      }
-    }
-  }
-  */
-
   uprintln("---Finished writing blocks to SPI Flash---");
 }
 
@@ -1346,6 +1326,8 @@ void brfs_write_to_flash()
 {
   brfs_write_fat_to_flash();
   brfs_write_blocks_to_flash();
+  // Reset changed blocks
+  memset(brfs_changed_blocks, 0, sizeof(brfs_changed_blocks));
 }
 
 /**

+ 44 - 20
BCC/BDOS/lib/shell.c

@@ -1,6 +1,6 @@
 // Max length of a single command
 #define SHELL_CMD_MAX_LENGTH 128
-#define SHELL_PATH "/bin/"
+#define SHELL_BIN_PATH "/bin/"
 
 word shell_cmd[SHELL_CMD_MAX_LENGTH];
 word shell_cmd_idx = 0;
@@ -69,15 +69,26 @@ void shell_parse_command()
 */
 void shell_print_help()
 {
-  GFX_PrintConsole("Available commands:\n");
-  GFX_PrintConsole("cd\n");
-  GFX_PrintConsole("clear\n");
-  GFX_PrintConsole("help\n");
+  GFX_PrintConsole(
+    "************\n"
+    "*BDOS Shell*\n"
+    "************\n"
+    "Available commands:\n"
+    "- cd <path>\n"
+    "- clear\n"
+    "- format <blk size> <blk cnt>\n"
+    "- sync\n"
+    "- help\n"
+    "\n"
+    "Programs are run from:\n"
+    "- /bin\n"
+    "- <current dir>\n"
+  );
 }
 
 /**
  * Attempt to run program from FS
- * If run_from_path is 1, the program is run from the SHELL_PATH
+ * If run_from_path is 1, the program is run from the SHELL_BIN_PATH
  * Returns 1 if program was found, 0 otherwise
 */
 word shell_run_program(word run_from_path)
@@ -93,7 +104,7 @@ word shell_run_program(word run_from_path)
   {
     if (run_from_path)
     {
-      strcpy(absolute_path, SHELL_PATH);
+      strcpy(absolute_path, SHELL_BIN_PATH);
       strcat(absolute_path, shell_tokens[0]);
     }
     else
@@ -228,7 +239,7 @@ void shell_list_directory(char* dir_path)
     struct brfs_dir_entry* dir_entry = (struct brfs_dir_entry*) (dir_addr + (i * sizeof(struct brfs_dir_entry)));
     if (dir_entry->filename[0] != 0)
     {
-      char decompressed_filename[16];
+      char decompressed_filename[17];
       strdecompress(decompressed_filename, (char*)&(dir_entry->filename));
       GFX_PrintConsole(decompressed_filename);
       GFX_PrintConsole(" FAT: ");
@@ -242,7 +253,6 @@ void shell_list_directory(char* dir_path)
   }
 }
 
-
 /**
  * Process dots in path so that ".." goes up one directory and "." is skipped
 */
@@ -353,8 +363,6 @@ void shell_change_directory()
     }
   }
 
-  uprintln(absolute_path);
-
   // Get dir entry of the path
   struct brfs_dir_entry* dir = brfs_stat(absolute_path);
 
@@ -372,6 +380,24 @@ void shell_change_directory()
   }
 }
 
+/**
+ * Format the filesystem
+*/
+void shell_format_filesystem()
+{
+  if (shell_num_tokens < 3)
+  {
+    GFX_PrintConsole("Usage: format <blk size> <blk cnt>\n");
+    return;
+  }
+
+  word block_size = strToInt(shell_tokens[1]);
+  word block_count = strToInt(shell_tokens[2]);
+  word full_format = 1;
+  brfs_format(block_count, block_size, "FPGC", full_format);
+  brfs_write_to_flash();
+}
+
 /**
  * Handle the command
 */
@@ -411,21 +437,21 @@ void shell_handle_command()
   {
     brfs_read_from_flash();
   }
+  else if (strcmp(shell_tokens[0], "dump") == 0)
+  {
+    // Dump FAT
+    brfs_dump_section(brfs_ram_storage+SUPERBLOCK_SIZE, strToInt(shell_tokens[1]), 16);
+  }
   else if (strcmp(shell_tokens[0], "format") == 0)
   {
-    word blocks = BDOS_DEFAULT_BLOCKS;
-    word words_per_block = BDOS_DEFAULT_BLOCK_SIZE;
-    word full_format = 1;
-    brfs_format(blocks, words_per_block, "FPGC5", full_format);
-    brfs_write_to_flash();
+    shell_format_filesystem();
   }
-  // Attempt to run program both from local dir and from SHELL_PATH
+  // Attempt to run program both from local dir and from SHELL_BIN_PATH
   else if (!shell_run_program(0))
   {
     if (!shell_run_program(1))
     {
       GFX_PrintConsole("Command not found\n");
-    
     }
   } 
 }
@@ -436,10 +462,8 @@ void shell_handle_command()
 void shell_init()
 {
   shell_clear_command();
-
   // Set path to root
   strcpy(shell_path, "/");
-
   shell_print_prompt();
 }
 

+ 2 - 2
BCC/BDOS/lib/stdlib.c

@@ -279,7 +279,8 @@ void strdecompress(char* dest, word* src)
     if (c == 0)
       break;
 
-    dest[i_dst++] = c;
+    dest[i_dst] = c;
+    i_dst++;
 
     if (byte_offset == 24)
     {
@@ -291,7 +292,6 @@ void strdecompress(char* dest, word* src)
       byte_offset += 8;
     }
   }
-
   // Terminate
   dest[i_dst] = 0;
 }

+ 91 - 0
BCC/userBDOS/checksum.c

@@ -0,0 +1,91 @@
+#define word char
+
+#include "lib/math.c"
+#include "lib/stdlib.c"
+#include "lib/sys.c"
+#include "lib/brfs.c"
+
+int main() 
+{
+  // Read number of arguments
+  word argc = shell_argc();
+  if (argc < 2)
+  {
+    bdos_println("Usage: checksum <file>");
+    return 1;
+  }
+  
+  // Read filename
+  char** args = shell_argv();
+  char* filename = args[1];
+
+  char absolute_path[MAX_PATH_LENGTH];
+  // Check if absolute path
+  if (filename[0] != '/')
+  {
+    char* cwd = fs_getcwd();
+    strcpy(absolute_path, cwd);
+    strcat(absolute_path, "/");
+    strcat(absolute_path, filename);
+  }
+  else
+  {
+    strcpy(absolute_path, filename);
+  }
+
+  // Get file size
+  struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(absolute_path);
+  uprint("Entry address: ");
+  uprintlnHex((word)entry);
+  if ((word)entry == -1)
+  {
+    bdos_println("File not found");
+    return 1;
+  }
+  word filesize = entry->filesize;
+
+  // Open file
+  word fd = fs_open(absolute_path);
+  if (fd == -1)
+  {
+    bdos_println("File not found");
+    return 1;
+  }
+
+  // Read file in chunks of 128 words
+  word checksum = filesize;
+  word buffer[128];
+  word read;
+  word i;
+  while (filesize > 0)
+  {
+    read = fs_read(fd, (char*)buffer, 128);
+    for (i = 0; i < read; i++)
+    {
+      checksum += buffer[i];
+    }
+    filesize -= read;
+  }
+
+  // Close file
+  fs_close(fd);
+
+  // Print checksum
+  bdos_print("Checksum: ");
+  bdos_printhex(checksum);
+  bdos_println("");
+
+  return 'q';
+}
+
+void interrupt()
+{
+  // Handle all interrupts
+  word i = get_int_id();
+  switch(i)
+  {
+    case INTID_TIMER1:
+      timer1Value = 1;  // Notify ending of timer1
+      break;
+  }
+}

+ 12 - 0
BCC/userBDOS/lib/brfs.c

@@ -0,0 +1,12 @@
+/**
+ * User library for file system operations
+*/
+
+struct brfs_dir_entry
+{
+  word filename[4];       // 4 chars per word
+  word modify_date;       // TBD when RTC added to FPGC
+  word flags;             // 32 flags, from right to left: directory, hidden 
+  word fat_idx;           // idx of first FAT block
+  word filesize;          // file size in words, not bytes
+};

+ 22 - 6
BCC/userBDOS/lib/sys.c

@@ -34,7 +34,8 @@
 #define SYS_FS_STAT 14
 #define SYS_FS_READDIR 15
 #define SYS_FS_GETCWD 16
-// Syscalls 17-19 are reserved for future use
+#define SYS_FS_SYNCFLASH 17
+// Syscalls 18-19 are reserved for future use
 #define SYS_SHELL_ARGC 20
 #define SYS_SHELL_ARGV 21
 #define SYS_USB_KB_BUF 99
@@ -116,7 +117,8 @@ void exit()
 */
 word hid_checkfifo()
 {
-  char* p = syscall(SYS_HID_CHECKFIFO);
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_HID_CHECKFIFO);
   return p[0];
 }
 
@@ -125,7 +127,8 @@ word hid_checkfifo()
 */
 word hid_fiforead()
 {
-  char* p = syscall(SYS_HID_READFIFO);
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_HID_READFIFO);
   return p[0];
 }
 
@@ -324,12 +327,23 @@ word fs_readdir(char* dirname)
 
 /**
  * Gets the current working directory in the filesystem
+ * Note: The pointer returned is only valid until the next syscall
 */
 char* fs_getcwd()
 {
   char* p = (char*) SYSCALL_RETVAL_ADDR;
   syscall(SYS_FS_GETCWD);
-  return (char*) p[0];
+  return p;
+}
+
+/**
+ * Synchronizes the filesystem with the flash memory
+*/
+word fs_syncflash()
+{
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_FS_SYNCFLASH);
+  return p[0];
 }
 
 /**
@@ -344,12 +358,13 @@ word shell_argc()
 
 /**
  * Returns the command line arguments
+ * Note: The pointer returned is only valid until the next syscall
 */
 char* shell_argv()
 {
   char* p = (char*) SYSCALL_RETVAL_ADDR;
   syscall(SYS_SHELL_ARGV);
-  return p[0];
+  return p;
 }
 
 /**
@@ -357,7 +372,8 @@ char* shell_argv()
 */
 word bdos_usbkey_held(word c)
 {
-  word* p = syscall(SYS_USB_KB_BUF);
+  char* p = (char*) SYSCALL_RETVAL_ADDR;
+  syscall(SYS_USB_KB_BUF);
   word* usbKeyBuffer = (char*) p[0];
   
   word i;

+ 6 - 7
BCC/userBDOS/mkdir.c

@@ -15,28 +15,27 @@ int main()
   }
   
   // Read directory name
-  char** dirname = shell_argv(1);
+  char** args = shell_argv();
+  char* dirname = args[1];
 
   char absolute_path[MAX_PATH_LENGTH];
   // Check if absolute path
-  if (dirname[1][0] != '/')
+  if (dirname[0] != '/')
   {
     char* cwd = fs_getcwd();
-    uprintln("CWD:");
-    uprintln(cwd);
     strcpy(absolute_path, cwd);
     strcat(absolute_path, "/");
-    strcat(absolute_path, dirname[1]);
+    strcat(absolute_path, dirname);
   }
   else
   {
-    strcpy(absolute_path, dirname[1]);
+    strcpy(absolute_path, dirname);
   }
 
   // Create directory
   if (fs_mkdir(absolute_path))
   {
-    bdos_println("Directory created");
+    fs_syncflash();
   }
   else
   {

+ 76 - 0
BCC/userBDOS/rm.c

@@ -0,0 +1,76 @@
+#define word char
+
+#include "lib/math.c"
+#include "lib/stdlib.c"
+#include "lib/sys.c"
+#include "lib/brfs.c"
+
+int main() 
+{
+  // Read number of arguments
+  word argc = shell_argc();
+  if (argc < 2)
+  {
+    bdos_println("Usage: rm <file/dir>");
+    return 1;
+  }
+  
+  // Read file/dir name
+  char** args = shell_argv();
+  char* fname = args[1];
+
+  char absolute_path[MAX_PATH_LENGTH];
+  // Check if absolute path
+  if (fname[0] != '/')
+  {
+    char* cwd = fs_getcwd();
+    strcpy(absolute_path, cwd);
+    strcat(absolute_path, "/");
+    strcat(absolute_path, fname);
+  }
+  else
+  {
+    strcpy(absolute_path, fname);
+  }
+
+  // Check if fname is a file or directory
+  struct brfs_dir_entry* entry = (struct brfs_dir_entry*)fs_stat(absolute_path);
+  if ((word)entry == -1)
+  {
+    bdos_println("File not found");
+    return 1;
+  }
+
+  if ((entry->flags & 0x01) == 0)
+  {
+    // File
+    if (fs_delete(absolute_path))
+    {
+      fs_syncflash();
+    }
+    else
+    {
+      bdos_println("Could not delete file");
+    }
+  }
+  else
+  {
+    // Directory
+    uprintln("del dir");
+    // TODO: Implement recursive deletion of directory
+  }
+
+  return 'q';
+}
+
+void interrupt()
+{
+  // Handle all interrupts
+  word i = get_int_id();
+  switch(i)
+  {
+    case INTID_TIMER1:
+      timer1Value = 1;  // Notify ending of timer1
+      break;
+  }
+}

+ 2 - 1
Documentation/docs/Software/BDOS/syscalls.md

@@ -33,6 +33,7 @@ Afterwards, BDOS will return from the syscall() function, pop the program counte
 | 14  | fs_stat        | char* path | -         | -          | Get file or directory information                | &#9745;     |
 | 15  | fs_readdir     | char* path | -         | -          | Read a directory (TODO: think what to return)    | &#9744;     |
 | 16  | fs_getcwd      | -          | -         | -          | Get the current working directory                | &#9745;     |
-|17-19| *reserved*     | -          | -         | -          | Reserved for future use                          |             |
+| 17  | fs_syncflash   | -          | -         | -          | Sync filesystem changes to SPI Flash             | &#9745;     |
+|18-19| *reserved*     | -          | -         | -          | Reserved for future use                          |             |
 | 20  | shell_argc     | -          | -         | -          | Get the number of command-line arguments         | &#9745;     |
 | 21  | shell_argv     | -          | -         | -          | Get the command-line arguments                   | &#9745;     |