Compare commits

...

2 commits

Author SHA1 Message Date
Egggggg 045d7e5106 guh 2023-07-12 19:38:17 -04:00
Egggggg 6115b75390 funky 2023-07-12 18:33:41 -04:00
2 changed files with 156 additions and 17 deletions

View file

@ -6,9 +6,15 @@
// reads the whole file
pub fn read(file: FileHandle) -> Vec<u8>
// reads up to 4096 bytes of the file
pub fn read_block(file: FileHandle) -> Vec<u8>
// overwrites the contents of the file
pub fn write(file: FileHandle, data: Vec<u8>)
// writes 4096 bytes to the file
pub fn write_block(file: FileHandle, data: Vec<u8>)
// opens a file for reading and writing
pub fn open(path: Path)
@ -48,7 +54,7 @@ All filesystems must expose at least these functions in order to work with the V
## Structure
### Mount Point Lookup Entry
### Mount Point
```
path_len: u64
@ -57,17 +63,31 @@ entries: u64
addr: u64
```
There is one of these for each mount point, stored sequentially within the root directory it belongs to. The list ends when it finds a `path_len` of 0
There is one of these for each mount point, stored sequentially. The list ends when it finds a path_len of 0
### Sub Part
### Inode
```
name_len: u64
name: [u8; <name_len>]
dir: u8
size: u64
next: u64
flags: u8
entries: u64
addr: u64
```
There can be many of these in a mount point, and they can be nested within eachother. dir is 1 if the part is a directory, or 0 if it's a file. size specifies the number of sub parts within a directory, or the number of bytes within a file
There can be many of these in a mount point, and they can be nested within eachother. If this is the last entry in the parent, `next` will refer to this inode, otherwise it will be the address of the next inode under the parent. `entries` specifies the number of inodes within a directory
#### Flags
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
| NA | NA | NA | NA | NA | NA | dir | mnt |
`dir` is set if the inode is a directory, or unset if it's a file.
`mnt` is set if the inode is a mount point
#### create_inode
1. traverse the path until we reach the last element or a nonexistent directory
2. if any path elements are mount points, request the filesystem belonging to it to create the item and if it succeeds create the inode

View file

@ -1,14 +1,133 @@
jmp r0, write
-- r255 is used as a bump allocator pointer
jal r0, r0, start
start:
li r255, data
-- Reads the file at the path pointed to by `name_addr`
--
-- inputs:
-- r8: name_addr
-- r9: name_len
-- outputs:
-- r8: data_addr
-- r9: data_len
-- returns to r1
read:
muli r16, r8, 8
ld r8, r16, data, 8
jal r0, r1, 0
-- Writes `data_len` bytes from `data_addr` to the file at the path pointed to by `name_addr`
-- This creates the file if it doesn't exist
--
-- inputs:
-- r8: name_addr
-- r9: name_len
-- r10: data_addr
-- r11: data_len
-- returns to r1
write:
li r8, 64
-- ctrl-a ctrl-c ctrl-v
brc r9, r8, 1
brc r10, r8, 2
brc r12, r8, 4
brc r16, r8, 8
brc r24, r8, 16
li r8, 32
muli r16, r8, 8
st r10, r16, data, 8
jal r0, r1, 0
fsdata:
-- Creates a mount point with the path located at `path_addr`
--
-- Structure:
-- path_len: u64
-- path: [u8; <path_len>]
-- entries: u64
-- fs: u64
-- addr: u64
--
-- inputs:
-- r8: path_addr
-- r9: path_len
-- r10: size
-- outputs:
-- r8: addr
-- returns to r1
mount:
-- Creates a new inode with a chosen path
--
-- inputs:
-- r8: path_addr
-- r9: path_len
-- r10: dir
-- outputs:
-- r8: addr
-- returns to r2
-- also uses regs r11-r15
create_inode:
-- back up path arguments
-- we need to use r8 and r9 as arguments for `find_inode`
brc r8, r16, 3
-- r8 will store the address of the next byte
li r9, 0 -- r9 will be store the length of the current part
li r10, data -- r10 will be used to refer to the current parent inode, so we'll start it at the root
cp r11, r8 -- r11 will store the base of the current part
li r12, 0 -- r12 will store the total length of the parsed path for comparing to `path_len`
-- store slash character bytes to compare to
-- `/` is 47, and `\` is 92
li r14, 42
li r15, 97
jal r0, r0, create_parse_path
create_parse_path:
-- we have the start address, now we need the length of the part
-- this can be found by adding 1 and jumping to `parse_path` if the next character is not a / or \
-- the next byte goes in r13
ld r13, r8, 0, 8
-- try to enter the inode if a slash was found
jeq r13, r14, create_enter_inode
jeq r13, r15, create_enter_inode
-- increment the byte pointer and check the next one
addi r8, r8, 1
addi r9, r9, 1
jal r0, r0, create_parse_path
create_enter_inode:
-- move the base of the part into r8
cp r8, r11
jal r3, r0, find_inode
jal r0, r2, 0
-- Finds an inode address by name within a parent inode
-- Returns with 0 in `r8` if there is no inode with the chosen name
--
-- inputs:
-- r8: name_addr
-- r9: name_len
-- r10: current_addr
-- outputs:
-- r8: addr
-- returns to r3
-- also uses regs r16-r24
find_inode:
ld r20, r10, 0, 1 -- load the name length to compare
jeq r9, r20, find_compare -- compare names if they're the same length
add r10, r10, r20 -- skip the name
addi r10, r10, 33 -- the structure other than the name is 33 bytes
jal r0, r0, find_inode
find_compare:
addi r16, r10, 8 -- r16 will store the base index of the string we're comparing against
li r17, 0 -- r17 will store the index of the byte we're checking
find_compare_loop:
-- try to batch up to 16 bytes at once
sub r18, r9, r17 -- get the number of bytes left
cmpi r19, r18, 16 -- r19 will be -1 if there are less than 16 bytes remaining
-- This is where all the VFS and FS data will be stored
-- VFS comes first, and FS starts at `data + 2048`
data: