From e35bbc1aa2106dc4fa1ab678b148e5bcd5e2441f Mon Sep 17 00:00:00 2001 From: Egggggg Date: Thu, 13 Jul 2023 21:31:22 -0400 Subject: [PATCH] hamburglar was here --- src/vfs.hbasm | 219 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 169 insertions(+), 50 deletions(-) diff --git a/src/vfs.hbasm b/src/vfs.hbasm index 2de3a88..e642df8 100644 --- a/src/vfs.hbasm +++ b/src/vfs.hbasm @@ -1,12 +1,47 @@ -- r255 is used as a bump allocator pointer -- r254 is -1 -- r253 is 33 (the number of bytes in an inode other than its name) +-- r252 is the root inode address +-- r251 is `/` (47) +-- r250 is `\` (92) jal r0, r0, start start: li r255, data li r254, -1 + li r253, 33 + li r251, 47 + li r250, 92 + + jal r1, r0, create_root + + -- allocate space for the path ("/e") + cp r8, r255 + addi r255, r255, 2 + li r9, 101 + -- store the path + st r251, r8, 0, 1 + st r9, r8, 1, 1 + + li r9, 2 + li r10, 0 + cp r32, r8 -- copy r8 to use the path again later + + jal r2, r0, create_inode + + cp r33, r8 -- copy r8 to compare against + + -- find `e` in / + cp r8, r32 + addi r8, r8, 1 + li r9, 1 + ld r10, r252, 17, 8 + jal r3, r0, find_inode + cp r34, r8 + + -- at this point r33 is the address we created /e at, and r34 is the address we found it at + ecall -- Reads the file at the path pointed to by `name_addr` -- @@ -53,74 +88,80 @@ write: -- r8: addr -- returns to r1 mount: + jal r0, r1, 0 -- do nothing for now + +-- Creates the root inode `/` +-- This should be run at the start of execution, before any other inodes are made +-- +-- returns to r1 +-- sets 252 to root inode's address +create_root: + cp r252, r255 + add r255, r255, r253 -- bump allocator past this inode + st r0, r252, 0, 8 -- `next` + li r8, 2 + st r8, r252, 8, 1 -- put 2 in `flags` + st r0, r252, 9, 8 -- 0 `size` for now + st r0, r252, 17, 8 -- 0 `addr` too + st r0, r252, 25, 8 -- 0 `name_len` + jal r0, r1, 0 -- Creates a new inode with a chosen path -- -- inputs: -- r8: path_addr -- r9: path_len --- r10: dir +-- r10: flags -- outputs: -- r8: addr +-- 1 if the path doesn't begin with a slash +-- 2 if a parent doesn't exist +-- 3 if a parent is a file -- returns to r2 -- modifies r8-r17 +-- indirectly modifies r19-r27 create_inode: cp r16, r9 -- copy `path_len` so we can use r9 - cp r17, r10 -- same with `dir` and r10 - -- r8 will store the address of the next byte - li r9, 0 -- r9 will store the parsed 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` + cp r17, r10 -- same with `flags` and r10 + -- r8 will store the address of the next bytes - -- store slash character bytes to compare to - li r14, 42 -- `/` is ascii 47 - li r15, 97 -- `\` is ascii 92 - - create_parse_path: - -- we have the start address, now we need the length of the part - -- 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 - jeq r12, r16, creation -- create the inode if this is the last part - jal r0, r0, create_parse_path - - create_enter_inode: - cp r8, r11 -- for `find_inode` argument - jal r3, r0, find_inode -- this will put the inode address in r8, or 0 if not found - jeq r8, r0, create_inode_return -- return if the inode wasn't found - cp r10, r8 - add r11, r11, r9 -- skip to the next path part - addi r11, r10, 1 -- also skip the slash - cp r8, r11 - add r12, r12, r9 -- increase the parsed length - addi r12, r12, 1 - li r9, 0 - jal r0, r0, create_parse_path + -- r9 becomes the address of the end name + -- r10 becomes the address of the direct parent, or an error code + -- r11 becomes the length of the end name + jal r4, r0, follow_path + li r24, 10 + jltu r10, r24, create_inode_fail creation: cp r8, r255 -- set the base address of this inode - add r255, r255, r9 -- - add r255, r255, r253 -- bump allocator past this inode - st r9, r8, 0, 8 -- store name_len + add r255, r255, r253 -- bump allocator past this inode + add r255, r255, r9 -- and its name + -- get the first entry under the parent inode + addi r24, r10, 17 -- r24 is now at the `addr` field of the parent + st r24, r8, 0, 8 -- make this inode's `next` field point to the previous first child + st r8, r10, 17, 8 -- point the parent's `addr` to this inode + st r17, r8, 8, 1 -- store `flags` + st r0, r8, 9, 8 -- store 0 for `size` until something gets added + st r0, r8, 17, 8 -- same for `addr` + st r9, r8, 25, 8 -- store `name_len` -- copy the name into the inode cp r24, r11 cp r25, r9 cp r26, r8 - addi r26, r253 - jal r4, r0, copy_buf - -- get the first entry under the parent inode - addi r25, r25, -- now r25 is at the `addr` field of the parent - + add r26, r26, r253 + -- increase the parent's size + ld r24, r10, 9, 1 + addi r24, r24, 1 + st r24, r10, 9, 1 + jal r4, r0, copy_buf create_inode_return: jal r0, r2, 0 + create_inode_fail: + cp r8, r10 + 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 passed name -- @@ -130,12 +171,20 @@ create_inode: -- r10: current_addr -- outputs: -- r8: addr +-- 1 if the inode doesn't exist -- returns to r3 -- modifies r10 and r19-r27 find_inode: ld r19, r10, 25, 8 -- load the name length to compare - ld r20, r27, 0, 8 -- load the `next` field of this inode + ld r20, r10, 0, 8 -- load the `next` field of this inode jeq r9, r19, find_compare -- only compare names if they're the same length + + ld r64, r10, 0, 8 + ld r65, r10, 8, 1 + ld r66, r10, 9, 24 + ecall + + jeq r10, r20, find_inode_fail -- fail if this is the last one cp r10, r20 jal r0, r0, find_inode -- else try the next inode @@ -157,19 +206,19 @@ find_inode: cmp_4: ld r26, r19, 0, 4 ld r24, r25, 0, 4 - add r21, r21, 4 + addi r21, r21, 4 jal r0, r0, cmp_end cmp_2: ld r26, r19, 0, 2 -- first 2 bytes ld r24, r25, 0, 2 - add r21, r21, 2 + addi r21, r21, 2 jal r0, r0, cmp_end cmp_1: ld r26, r19, 0, 1 -- get the byte to compare ld r24, r25, 0, 1 -- and the byte to compare with - add r21, r21, 1 + addi r21, r21, 1 cmp_end: jeq r26, r24, find_compare_loop -- continue if this set matches @@ -180,6 +229,10 @@ find_inode: find_inode_return: jal r0, r3, 0 + find_inode_fail: + li r8, 1 + jal r0, r3, 0 + -- Copies a buffer -- -- inputs: @@ -199,7 +252,7 @@ copy_buf: jeq r27, r0, copy_end addi r24, r24, 4 addi r26, r26, 4 - addi r25, -4 + addi r25, r25, -4 jal r0, r0, copy_buf copy_2: @@ -207,7 +260,7 @@ copy_buf: jeq r27, r0, copy_end addi r24, r24, 2 addi r26, r26, 2 - addi r25, -2 + addi r25, r25, -2 jal r0, r0, copy_buf copy_1: @@ -216,6 +269,72 @@ copy_buf: copy_end: jal r0, r4, 0 +-- Parses a path, returning the address of the direct parent +-- +-- inputs: +-- r8: path_addr +-- r16: path_len +-- outputs: +-- r9: name_len +-- r10: parent_addr +-- 1 if the direct parent wasn't found +-- 2 if a parent is a file +-- r11: name_addr +-- returns to r4 +-- modifies r12-r13 +follow_path: + li r9, 0 -- r9 will store the parsed length of the current part + cp r10, r252 -- 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` + + -- skip leading slash if it exists + ld r13, r8, 0, 1 + jeq r13, r14, skip_leading + jeq r13, r15, skip_leading + li r8, 1 -- return with a 1 in r8 + jal r0, r0, parse_return + + skip_leading: + addi r8, r8, 1 + addi r9, r9, 1 + + parse_loop: + -- we have the start address, now we need the length of the part + -- the next byte goes in r13 + ld r13, r8, 0, 1 + -- try to enter the inode if a slash was found + jeq r13, r251, enter_inode + jeq r13, r250, enter_inode + -- increment the byte pointer and check the next one + addi r8, r8, 1 + addi r9, r9, 1 + jeq r12, r16, parse_return -- return inode if this is the last part + jal r0, r0, parse_loop + + enter_inode: + cp r8, r11 -- for `find_inode` argument + jal r3, r0, find_inode -- this will put the inode address in r8, or 0 if not found + jeq r8, r0, parse_fail -- fail if the inode wasn't found + cp r10, r8 + add r11, r11, r9 -- skip to the next path part + addi r11, r11, 1 -- also skip the slash + cp r8, r11 + add r12, r12, r9 -- increase the parsed length + addi r12, r12, 1 -- including the slash + li r9, 0 + jal r0, r0, parse_loop + + parse_return: + jal r0, r4, 0 + + parse_fail: + li r10, 1 + jal r0, r4, 0 + + parse_parent_file: + li r10, 2 + jal r0, r4, 0 -- This is where all the VFS and FS data will be stored -- VFS comes first, and FS starts at `data + 2048`