Browse Source

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 tháng trước cách đây
mục cha
commit
6a15b3499f

+ 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;     |