diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..135458b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,17 @@ +# Set default behavior to automatically normalize line endings +* text=auto + +# Force LF for source files (Unix-style, common for C projects) +*.c text eol=lf +*.h text eol=lf +*.ld text eol=lf +*.sh text eol=lf + +# Binary files +*.bin binary +*.elf binary +*.tar binary +*.png binary +*.ico binary +*.svg binary + diff --git a/README.md b/README.md index 4c681df..aa62f03 100644 --- a/README.md +++ b/README.md @@ -14,4 +14,27 @@ The book only covers the basics of an operating system. You can do more with the | --- | --- | | [Shutdown command](https://github.com/nuta/operating-system-in-1000-lines/pull/59/files) | [@calvera](https://github.com/calvera) | -Let me know if you have implemented something interesting! + + +I added + +ls +image + + +addf +image + +readf +image + +writef + +image + + + + + + +commands and syscalls needed diff --git a/common.c b/common.c index 9cd9e25..66eafa4 100644 --- a/common.c +++ b/common.c @@ -22,6 +22,19 @@ char *strcpy(char *dst, const char *src) { *d = '\0'; return dst; } +int strncmp(const char *s1, const char *s2, int n) { + for (int i = 0; i < n; i++) { + unsigned char c1 = (unsigned char)s1[i]; + unsigned char c2 = (unsigned char)s2[i]; + + if (c1 != c2) + return c1 - c2; + if (c1 == '\0') // Eğer birisi '\0' ise karşılaştırmayı bitir + return 0; + } + return 0; +} + int strcmp(const char *s1, const char *s2) { while (*s1 && *s2) { diff --git a/common.h b/common.h index 286df8a..6abd316 100644 --- a/common.h +++ b/common.h @@ -25,9 +25,14 @@ typedef uint32_t vaddr_t; #define SYS_EXIT 3 #define SYS_READFILE 4 #define SYS_WRITEFILE 5 - +#define SYS_ADDFILE 6 +#define SYS_READF 7 +#define SYS_ADDF 8 +#define SYS_WRITEF 9 +#define SYS_LS 10 void *memset(void *buf, char c, size_t n); void *memcpy(void *dst, const void *src, size_t n); char *strcpy(char *dst, const char *src); int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, int n); void printf(const char *fmt, ...); diff --git a/kernel.c b/kernel.c index ec7b666..97a8472 100644 --- a/kernel.c +++ b/kernel.c @@ -497,13 +497,100 @@ void handle_syscall(struct trap_frame *f) { yield(); } break; + case SYS_READF: { + const char *filename = (const char *) f->a0; + struct file *file = fs_lookup(filename); + if (!file) { + f->a0 = -1; // dosya yok + break; + } + + // Dosya içeriğini console’a yaz + for (int i = 0; i < file->size; i++) + putchar(file->data[i]); + + f->a0 = file->size; + break; + +} +case SYS_LS: { + printf("Files:\n"); + for (int i = 0; i < FILES_MAX; i++) { + if (files[i].in_use) { + printf(" %s (size: %d)\n", files[i].name, files[i].size); + } + } + f->a0 = 0; + break; +} + +case SYS_ADDF: { + const char *filename = (const char *) f->a0; + struct file *file = NULL; + for (int i = 0; i < FILES_MAX; i++) { + if (!files[i].in_use) { + file = &files[i]; + break; + } + } + if (!file) { f->a0 = -1; break; } + file->in_use = true; + strcpy(file->name, filename); + file->size = 0; + fs_flush(); + f->a0 = 0; + break; +} + +case SYS_WRITEF: { + const char *filename = (const char *) f->a0; + struct file *file = fs_lookup(filename); + if (!file) { f->a0 = -1; break; } + + char *buf = (char *) f->a1; + int len = f->a2; + if (len > (int) sizeof(file->data)) + len = sizeof(file->data); + memcpy(file->data, buf, len); + file->size = len; + fs_flush(); + f->a0 = len; + break; +} + + + case SYS_ADDFILE: { + const char *filename = (const char *) f->a0; + + // find free slot + struct file *file = NULL; + for (int i = 0; i < FILES_MAX; i++) { + if (!files[i].in_use) { + file = &files[i]; + break; + } + } + + if (!file) { + f->a0 = -1; // fail + break; + } + + file->in_use = true; + strcpy(file->name, filename); + file->size = 0; // boş dosya + fs_flush(); // diske yaz + f->a0 = 0; // success + break; + } + case SYS_EXIT: printf("process %d exited\n", current_proc->pid); current_proc->state = PROC_EXITED; yield(); PANIC("unreachable"); case SYS_READFILE: - case SYS_WRITEFILE: { + case SYS_WRITEFILE: { const char *filename = (const char *) f->a0; char *buf = (char *) f->a1; int len = f->a2; diff --git a/kernel.h b/kernel.h index 6969d99..95f32fb 100644 --- a/kernel.h +++ b/kernel.h @@ -15,7 +15,7 @@ #define PAGE_X (1 << 3) #define PAGE_U (1 << 4) #define USER_BASE 0x1000000 -#define FILES_MAX 2 +#define FILES_MAX 3 #define DISK_MAX_SIZE align_up(sizeof(struct file) * FILES_MAX, SECTOR_SIZE) #define SECTOR_SIZE 512 #define VIRTQ_ENTRY_NUM 16 diff --git a/run_on_ubuntu.sh b/run_on_ubuntu.sh new file mode 100644 index 0000000..31e3ce1 --- /dev/null +++ b/run_on_ubuntu.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -xue + +QEMU=qemu-system-riscv32 +CC=/usr/bin/clang +OBJCOPY=/usr/bin/llvm-objcopy-18 + +CFLAGS="-std=c11 -O2 -g3 -Wall -Wextra --target=riscv32-unknown-elf -fuse-ld=lld -fno-stack-protector -ffreestanding -nostdlib" + +# Build the shell. +$CC $CFLAGS -Wl,-Tuser.ld -Wl,-Map=shell.map -o shell.elf shell.c user.c common.c +$OBJCOPY --set-section-flags .bss=alloc,contents -O binary shell.elf shell.bin +$OBJCOPY -Ibinary -Oelf32-littleriscv shell.bin shell.bin.o + +# Build the kernel. +$CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \ + kernel.c common.c shell.bin.o + +(cd disk && tar cf ../disk.tar --format=ustar *.txt) + +$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \ + -d unimp,guest_errors,int,cpu_reset -D qemu.log \ + -drive id=drive0,file=disk.tar,format=raw,if=none \ + -device virtio-blk-device,drive=drive0,bus=virtio-mmio-bus.0 \ + -kernel kernel.elf diff --git a/shell.c b/shell.c index 0bff8e2..d13c8e9 100644 --- a/shell.c +++ b/shell.c @@ -2,7 +2,7 @@ void main(void) { while (1) { -prompt: + prompt: printf("> "); char cmdline[128]; for (int i = 0;; i++) { @@ -11,7 +11,7 @@ void main(void) { if (i == sizeof(cmdline) - 1) { printf("command line too long\n"); goto prompt; - } else if (ch == '\r') { + } else if (ch == '\r' || ch == '\n') { // ENTER tuşunu hem \r hem \n olarak kontrol et printf("\n"); cmdline[i] = '\0'; break; @@ -20,19 +20,48 @@ void main(void) { } } - if (strcmp(cmdline, "hello") == 0) + if (strcmp(cmdline, "hello") == 0) { printf("Hello world from shell!\n"); - else if (strcmp(cmdline, "exit") == 0) + } else if (strcmp(cmdline, "exit") == 0) { exit(); - else if (strcmp(cmdline, "readfile") == 0) { - char buf[128]; - int len = readfile("hello.txt", buf, sizeof(buf)); - buf[len] = '\0'; - printf("%s\n", buf); } - else if (strcmp(cmdline, "writefile") == 0) - writefile("hello.txt", "Hello from shell!\n", 19); - else + else if (strcmp(cmdline, "ls") == 0) { + ls(); + } + else if (strncmp(cmdline, "readf ", 6) == 0) { + char *filename = cmdline + 6; + int ret = readf(filename); + if (ret < 0) + printf("file not found: %s\n", filename); + } else if (strncmp(cmdline, "addf ", 5) == 0) { + char *filename = cmdline + 5; + int ret = addf(filename); + if (ret == 0) + printf("file \"%s\" added successfully!\n", filename); + else + printf("failed to add file \"%s\"\n", filename); + } else if (strncmp(cmdline, "writef ", 7) == 0) { + char *filename = cmdline + 7; + char buf[128]; + printf("Enter content (end with ENTER): "); + int i = 0; + for (;;) { + char ch = getchar(); + if (ch == '\r' || ch == '\n' || i == sizeof(buf) - 1) { + buf[i] = '\0'; + break; + } + putchar(ch); + buf[i++] = ch; + } + int ret = writef(filename, buf, i); + if (ret >= 0) + printf("written %d bytes to %s\n", ret, filename); + else + printf("failed to write to %s\n", filename); + } else { printf("unknown command: %s\n", cmdline); + } } } + diff --git a/user.c b/user.c index c0854fa..cff4192 100644 --- a/user.c +++ b/user.c @@ -15,6 +15,9 @@ int syscall(int sysno, int arg0, int arg1, int arg2) { return a0; } +int ls(void) { + return syscall(SYS_LS, 0, 0, 0); +} void putchar(char ch) { syscall(SYS_PUTCHAR, ch, 0, 0); @@ -32,11 +35,27 @@ int writefile(const char *filename, const char *buf, int len) { return syscall(SYS_WRITEFILE, (int) filename, (int) buf, len); } +int addfile(const char *filename) { + return syscall(SYS_ADDFILE, (int) filename, 0, 0); +} +int readf(const char *filename) { + return syscall(SYS_READF, (int)filename, 0, 0); +} + +int addf(const char *filename) { + return syscall(SYS_ADDF, (int)filename, 0, 0); +} + +int writef(const char *filename, const char *buf, int len) { + return syscall(SYS_WRITEF, (int)filename, (int)buf, len); +} + + __attribute__((noreturn)) void exit(void) { syscall(SYS_EXIT, 0, 0, 0); for (;;); } - + __attribute__((section(".text.start"))) __attribute__((naked)) void start(void) { diff --git a/user.h b/user.h index 8c0c859..a0728be 100644 --- a/user.h +++ b/user.h @@ -11,4 +11,10 @@ void putchar(char ch); int getchar(void); int readfile(const char *filename, char *buf, int len); int writefile(const char *filename, const char *buf, int len); +int addfile(const char *filename); +int readf(const char *filename); +int addf(const char *filename); +int writef(const char *filename, const char *buf, int len); +int ls(void); + __attribute__((noreturn)) void exit(void);