From 466cd4021fa324c726d1fa68eebc202c53aec5f0 Mon Sep 17 00:00:00 2001
From: Amelia Coutard <eliottulio.coutard@gmail.com>
Date: Mon, 27 Nov 2023 00:53:46 +0100
Subject: [PATCH] Changed the future API a bit. Also, changed the syscall
 handler a bit because 1) %rdx was broken and 2) I was actually probably never
 gonna need the second return register, because of that new API

---
 doc.txt            | 107 +++++++++++++++++++--------------------------
 kernel/src/ring3.S |   4 +-
 2 files changed, 46 insertions(+), 65 deletions(-)

diff --git a/doc.txt b/doc.txt
index 142373f..2c6622e 100644
--- a/doc.txt
+++ b/doc.txt
@@ -12,30 +12,25 @@ isos documentation:
 0000'7FFF'FFFF'0000 ↔ 0000'8000'0000'0000 - stack: 64KiB
 -- Invalid addresses --
 FFFF'8000'0000'0000 ↔ FFFF'C000'0000'0000 - physical memory: 64TiB
-FFFF'C000'0000'0000 ↔ ____'____'____'____ - process information table: 2048 processes, 4093 ports/process
-____'____'____'____ ↔ FFFF'FFFF'8000'0000 - unmapped
+FFFF'C000'0000'0000 ↔ FFFF'FFFF'8000'0000 - process information tables:
+	open file descriptors, namespaces, etc.
 FFFF'FFFF'8000'0000 ↔10000'0000'0000'0000 - kernel: 2GiB
 
 ---------------------------
 
-The port is the IPC method of this kernel. There are two types of ports.
-Server ports are points where a server will receive a message. They can receive
-	a message from any number of client ports.
-Client ports are points where a client can send a message. A client port always points
-	to a single server port.
+All the IPC is handled via many, many files.
+Also, a filename must be a sequence of non-0, non-\n, non-control-character, legal utf-8 codepoints.
+A directory will, for the purposes of system calls that operate on file contents, appear as a read-only
+	file containing each of the file names of its contents, each file name followed by a single \n.
+At boot, the first module gets access to a special filesystem, that only it has access to.
+	- /serial: R/W, serial I/O
+All the other modules get only a single open file, corresponding to the file system exposed by the first module's process.
 
 ---------------------------
 
 Data types:
 
-pid_t   = int64_t;
-sport_t = int64_t;
-cport_t = int64_t;
-port_t  = int64_t; // Either a server port or a client port.
-struct handler {
-	pid_t pid;
-	cport_t port;
-};
+fd_t = int64_t; // Client-side file (or directory) descriptor.
 
 ---------------------------
 
@@ -43,50 +38,38 @@ The system calls:
 
 Input registers in order: %rdi, %rsi, %rdx, %r10, %r8, %r9.
 In %rax, the syscall id is specified.
-If the operation succeeds, %rax contains the result (think SystemV ABI) (≥ 0). If it fails, %rax contains the opposite of the error code. (< 0)
-The only registers clobbered are %rcx, %r11, %rax, %rdx. (The last two are the return registers.)
-
-sport_t make_sport();
-	Creates a server port, with no associated clients.
-cport_t make_cport(sport_t);
-	Creates a client port associated with the given server port.
-cport_t copy_cport(cport_t);
-	Takes a client port, and returns a new client port that points to the same server port.
-
-bool has_cports(sport_t);
-	Takes a server port, and returns whether or not it has any client ports.
-void close(port_t);
-	Close a port. It no longer exists in this process.
-	If it was a server port, any use of any of its client ports for the purpose
-		of communication will fail with ERR_CLOSED_P.
-	If it was a client port,
-		If it wasn't the server's last client, nothing happens.
-		If it was, however, the server will be notified by way of singnalling on the next wait call.
-Program termination implicitly calls close on all the program's ports.
-
-sport_t wait();
-	Block until one of the server ports of this process receives a message or loses its last client.
-	Returns the server port in question.
-
-{int64_t out_s, uint64_t user_error_code} call(cport_t p, int64_t in_s, const void* in, cport_t* io_p, int64_t out_s, void* out);
-	Blocks until the server refered to by p replies. //, or reports an error.
-handler receive(sport_t p);
-	Block until any client sends a message to the port p.
-int64_t receive_size(handler client);
-	Get the size of the message that client is sending.
-cport_t receive_message(handler client, int64_t out_s, void* out);
-	Gets the data of the message that client is sending.
-	If the client is sending a port as well, return it, return 0 otherwise.
-
-void reply(handler caller, int64_t in_s, const void* in, cport_t in_p);
-	Invalidates caller.
-	Replies to the caller with the data of length in_s in `in`.
-	If in_p is non-0, a copy of it is sent as well.
-// void forward(cport_t to, handler caller, int64_t sub_begin, int64_t sub_len);
-	// Invalidates caller.
-	// Transfers message to `to` (reply will go to the original client still).
-	// 0 ≤ sub_begin ≤ receive_size(client) and 0 ≤ sub_len ≤ receive_size(client) - sub_begin.
-	// The data transferred will only be that in data[sub_begin; sub_begin + sub_len[, ∅ if sub_len == 0.
-// void error(handler caller, uint64_t error_code);
-	// Invalidates caller.
-	// Call gets ERR_USER, with the second value set to error_code.
+If the operation succeeds, %rax contains the result (think SystemV ABI) (≥ 0). If it fails, %rax contains -1.
+The only registers clobbered are %rcx, %r11, and %rax.
+
+enum open_options {
+	MODE_RO = 0x1
+	MODE_WO = 0x2
+	MODE_RW = MODE_RO | MODE_WO
+	MODE_DIRECTORY = 0x4
+	OPTION_INPLACE = 0x8
+};
+
+fd_t open(fd_t wd, char const path[path_len], ssize_t path_len, open_options options /* See enum above. */);
+	Options must be one of ro, wo or rw, |-ed with any (including multiple) of MODE_DIRECTORY and OPTION_INPLACE
+	Try to open path, relative to wd.
+	If path is absolute, wd can actually not be an open file (but it still needs to be >= 0, for in_place to work).
+	If OPTION_INPLACE, makes wd point to the opened file/folder in case of success, and return wd.
+	If not, doesn't change wd, and returns a new fd pointing to the opened file/folder.
+	If MODE_DIRECTORY, open fails if path refers to a non-directory file.
+	If not, open fails if path refers to a directory.
+	When open fails, it returns -1 (as all syscalls) and the program continues as though open was never called.
+
+ssize_t read(fd_t file, char data[len], ssize_t len);
+	Read up to len characters from file.
+	Return the number of actually read characters, or -1 on error.
+
+ssize_t write(fd_t file, char data[len], ssize_t len);
+	Write up to len characters to file.
+	Return the number of actually written characters, or -1 on error.
+
+ssize_t fseek(fd_t file, ssize_t offset, int from);
+	If from is 0, seek offset bytes from start.
+	If from is 1, seek offset bytes from current file position.
+	If from is 2, seek offset bytes from end of file.
+	In the case of non-seekable files (i.e. pipes 'n shit), this is a noop.
+	Returns the new file position, in bytes from the start.
diff --git a/kernel/src/ring3.S b/kernel/src/ring3.S
index 43c8192..4bb41c7 100644
--- a/kernel/src/ring3.S
+++ b/kernel/src/ring3.S
@@ -66,7 +66,6 @@ syscall_64bit_handler:
 	callq *syscalls_call_table(, %rax, 8)
 syscall_end:
 	mov %rax, %rbp # Save the return
-	mov %rdx, %rbx # registers.
 	# Get process data location:
 	mov current_pid, %rdi
 	call get_process
@@ -75,8 +74,7 @@ syscall_end:
 		mov 8 + \reg * 8(%rax), %rbx # Get %r\reg
 		mov %rbx, save_regs_tmp + \reg * 8 # And restore it.
 	.endr
-	mov %rbp, save_reg_tmp_rax # Restore the return
-	mov %rbx, save_reg_tmp_rdx # registers as well.
+	mov %rbp, save_reg_tmp_rax # Restore the return register as well.
 	mov 0x88(%rax), %rbx # Save the rip in place of rcx, because this is sysret.
 	mov %rbx, save_reg_tmp_rcx
 	# Really restore all regs:
-- 
2.46.0