diff --git a/Makefile b/Makefile index a5fb9a4..edc5a21 100644 --- a/Makefile +++ b/Makefile @@ -21,10 +21,6 @@ CC_FLAGS=-Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fstack-protector -fn LD := x86_64-elf-ld $(ELFFILE): $(BUILDDIR) $(OBJFILES) - nasm -f bin user/hello.S -o $(BUILDDIR)/hello - nasm -f bin user/pedicel.S -o $(BUILDDIR)/pedicel - tar cvf $(BUILDDIR)/initfs.tar -C $(BUILDDIR) hello pedicel - nasm -f elf64 src/arch/x86/idt.S -o $(BUILDDIR)/idt_stub.o $(LD) -o $(ELFFILE) -T linker.ld $(OBJFILES) $(BUILDDIR)/idt_stub.o # Get the symbols for debugging @@ -45,7 +41,11 @@ limine/limine: git clone https://github.com/limine-bootloader/limine.git --branch=v9.x-binary --depth=1 $(MAKE) -C limine -initfs: +.PHONY: user +user: + nasm -f bin user/hello.S -o $(BUILDDIR)/hello + nasm -f bin user/pedicel.S -o $(BUILDDIR)/pedicel + tar cvf $(BUILDDIR)/initfs.tar -C $(BUILDDIR) hello pedicel -C ../user wow.txt build-iso: limine/limine $(ELFFILE) rm -rf iso_root diff --git a/docs/MANUAL.md b/docs/MANUAL.md index c55e67a..b8dcda2 100644 --- a/docs/MANUAL.md +++ b/docs/MANUAL.md @@ -41,8 +41,12 @@ The recommended hardware to run PepperOS is the following: ## III. Syscall table The syscall interface in the Pepper kernel uses the System V ABI convention for argument order. +It vaguely mimics Unix-like systems. Name | Number (%rax) | arg0 (%rdi) | arg1 (%rsi) | arg2 (%rdx) | |---|---|---|---|---| -| sys_write | 1 | unsigned int fd | const char* buf | size_t count | | -| sys_exit | 60 | int error_code | | | | \ No newline at end of file +| sys_read | 0 | unsigned int fd | char* buf | size_t count | +| sys_write | 1 | unsigned int fd | const char* buf | size_t count | +| sys_open | 2 | const char* filename | int flags | | +| sys_close | 3 | unsigned int fd | | | +| sys_exit | 60 | int error_code | | | \ No newline at end of file diff --git a/include/fs/initfs.h b/include/fs/initfs.h index 266ce33..a8c12c9 100644 --- a/include/fs/initfs.h +++ b/include/fs/initfs.h @@ -11,7 +11,7 @@ int initfs_init(struct limine_file* tar_file); int tar_lookup(unsigned char* archive, char* filename, char** out); -int tar_read(char* filename, char** buf); int tar_exists(const char* filename); +int tar_read(char* filename, char* out, int count, int offset); #endif \ No newline at end of file diff --git a/include/kernel.h b/include/kernel.h index cb66dc0..3d8d0b7 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -14,7 +14,8 @@ enum ErrorCodes { EIO, // Input/output error ENOENT, // No entry EBADFD, // Bad file descriptor - EMFILE // Too many open files + EMFILE, // Too many open files + EINVAL // Invalid argument }; #define CLEAR_INTERRUPTS __asm__ volatile("cli") diff --git a/src/arch/x86/syscall.c b/src/arch/x86/syscall.c index b402877..15f9128 100644 --- a/src/arch/x86/syscall.c +++ b/src/arch/x86/syscall.c @@ -70,10 +70,12 @@ int sys_read(unsigned int fd, char* buf, size_t count) return -EBADFD; // File descriptor wasn't open } // Here fd refers to a valid opened file.. - int sz = tar_read(current_process->fdt[fd].filename,&buf); + int sz = tar_read(current_process->fdt[fd].filename, buf, count, + current_process->fdt[fd].cursor); if (sz == 0) { return -ENOENT; } else { + current_process->fdt[fd].cursor += sz; return sz; } } @@ -82,27 +84,25 @@ int sys_read(unsigned int fd, char* buf, size_t count) } // TODO: Should have a return value: number of bytes written on success, -1 on error (errno set) -void sys_write(unsigned int fd, const char* buf, size_t count) +int sys_write(unsigned int fd, const char* buf, size_t count) { switch (fd) { case 1: //stdout - for (size_t i=0; istatus = DEAD; - DEBUG("exiting process PID=%u name=%s", current_process->pid, current_process->name); + DEBUG("(pid=%u, name=%s)", current_process->pid, current_process->name); + return error_code; } /* @@ -125,29 +125,36 @@ void sys_exit(int error_code) */ struct cpu_status* syscall_handler(struct cpu_status* regs) { - DEBUG("Syscall %lx with (arg0=%lx arg1=%lx)", regs->rax, regs->rdi, regs->rsi); - switch (regs->rax) { - case 0: //sys_read + case 0: + DEBUG("sys_read(fd=%u, buf=%p, count=%u)", regs->rdi, regs->rsi, regs->rdx); regs->rax = sys_read(regs->rdi, (char*)regs->rsi, regs->rdx); break; - case 1: //sys_write - sys_write(regs->rdi, (char*)regs->rsi, regs->rdx); + case 1: + DEBUG("sys_write(fd=%u, buf=%p, count=%u)", regs->rdi, regs->rsi, regs->rdx); + regs->rax = sys_write(regs->rdi, (char*)regs->rsi, regs->rdx); break; case 2: + DEBUG("sys_open(filename=%s, flags=%u)", regs->rdi, regs->rsi); regs->rax = sys_open((const char*)regs->rdi, regs->rsi); break; case 3: + DEBUG("sys_close(fd=%u)", regs->rdi); regs->rax = sys_close(regs->rdi); break; - case 60: //sys_exit - sys_exit(regs->rdi); + case 60: + DEBUG("sys_exit(error_code=%d)", regs->rdi); + regs->rax = sys_exit(regs->rdi); break; - default: // bad syscall + default: + DEBUG("Bad syscall! (rax=%p, rdi=%p, rsi=%p, rdx=%p)", + regs->rax, regs->rdi, regs->rsi, regs->rdx); regs->rax = 0xbad515ca11; break; } + DEBUG("returned rax=%p (%u)", regs->rax, regs->rax); + return regs; } \ No newline at end of file diff --git a/src/fs/initfs.c b/src/fs/initfs.c index 2e49243..40b314c 100644 --- a/src/fs/initfs.c +++ b/src/fs/initfs.c @@ -42,7 +42,7 @@ int tar_oct2bin(unsigned char* str, int size) * * Return: * $filesize - size of the file, if found - * $0 - file not found + * $-ENOENT - file not found */ int tar_lookup(unsigned char* archive, char* filename, char** out) { @@ -56,21 +56,39 @@ int tar_lookup(unsigned char* archive, char* filename, char** out) } ptr += (((filesize + 511) / 512) + 1) * 512; } - return 0; + return -ENOENT; } /* - * tar_read - read a file in the TAR file + * tar_read - read a file in the TAR archive * @filename: file to read (absolute path) - * @out: out buffer (if file is found) + * @out: where to store file data if found + * @count: amount of bytes to read + * @offset: read from byte offset (0 for none) * * Return: * $filesize - size of the file, if found - * $0 - file not found + * $-ENOENT - file not found */ -int tar_read(char* filename, char** buf) +int tar_read(char* filename, char* out, int count, int offset) { - return tar_lookup(archive_start_addr, filename, buf); + char* file_data; + int filesize = tar_lookup(archive_start_addr, filename, &file_data); + + if (filesize <= 0) { + return filesize; + } + + if (offset >= filesize) { + return -EINVAL; + } + + int remaining = filesize - offset; + int to_read = remaining < count ? remaining : count; + + memcpy(out, file_data + offset, to_read); + + return to_read; } /* diff --git a/user/pedicel.S b/user/pedicel.S index e1b92ef..28bab89 100644 --- a/user/pedicel.S +++ b/user/pedicel.S @@ -1,7 +1,8 @@ bits 64 section .data -hello db 0x0A, 0x0D, "User program 2 speaking", 0x0A, 0x0D, 0 +hello db 0x0A, 0x0D, "TEST PROGRAM...", 0x0A, 0x0D, 0 +filename db "wow.txt", 0 section .text @@ -9,7 +10,29 @@ _start: mov rax, 0x1 ;sys_write mov rdi, 0x1 ;stdout lea rsi, [rel hello] - mov rdx, 27 ;count + mov rdx, 19 ;count + int 0x80 + + ; Open a file + mov rax, 0x2 ;sys_open + lea rdi, [rel filename] ;filename + mov rsi, 0x0 ;flags + int 0x80 + + mov rdi, rax ;fd + mov rax, 0x0 ;sys_read + lea rsi, [rel buf] ;buf + mov rdx, 33 ;count + int 0x80 + + mov rax, 0x1 ;sys_write + mov rdi, 0x1 ;stdout + lea rsi, [rel buf] ;buf + mov rdx, 33 ;count + int 0x80 + + mov rax, 0x3 ;sys_close + mov rdi, 0x3 ;fd int 0x80 ; when we are ready to have an os specific toolchain, @@ -22,4 +45,7 @@ _start: int 0x80 .loop: - jmp .loop \ No newline at end of file + jmp .loop + +section .bss +buf resb 10 \ No newline at end of file diff --git a/user/wow.txt b/user/wow.txt new file mode 100644 index 0000000..ed7191d --- /dev/null +++ b/user/wow.txt @@ -0,0 +1 @@ +hi from a file opened in usermode \ No newline at end of file