USER_ELF := user/init.elf
ECHO_ELF := user/echo.elf
SH_ELF := user/sh.elf
+ CAT_ELF := user/cat.elf
+ LS_ELF := user/ls.elf
+ MKDIR_ELF := user/mkdir.elf
+ RM_ELF := user/rm.elf
INITRD_IMG := initrd.img
MKINITRD := tools/mkinitrd
endif
$(SH_ELF): user/sh.c user/linker.ld
@i686-elf-gcc -m32 -I include -ffreestanding -fno-pie -no-pie -nostdlib -Wl,-T,user/linker.ld -o $(SH_ELF) user/sh.c user/errno.c
-$(INITRD_IMG): $(MKINITRD) $(USER_ELF) $(ECHO_ELF) $(SH_ELF)
- @./$(MKINITRD) $(INITRD_IMG) $(USER_ELF):bin/init.elf $(ECHO_ELF):bin/echo.elf $(SH_ELF):bin/sh
+$(CAT_ELF): user/cat.c user/linker.ld
+ @i686-elf-gcc -m32 -I include -ffreestanding -fno-pie -no-pie -nostdlib -Wl,-T,user/linker.ld -o $(CAT_ELF) user/cat.c user/errno.c
+
+$(LS_ELF): user/ls.c user/linker.ld
+ @i686-elf-gcc -m32 -I include -ffreestanding -fno-pie -no-pie -nostdlib -Wl,-T,user/linker.ld -o $(LS_ELF) user/ls.c user/errno.c
+
+$(MKDIR_ELF): user/mkdir.c user/linker.ld
+ @i686-elf-gcc -m32 -I include -ffreestanding -fno-pie -no-pie -nostdlib -Wl,-T,user/linker.ld -o $(MKDIR_ELF) user/mkdir.c user/errno.c
+
+$(RM_ELF): user/rm.c user/linker.ld
+ @i686-elf-gcc -m32 -I include -ffreestanding -fno-pie -no-pie -nostdlib -Wl,-T,user/linker.ld -o $(RM_ELF) user/rm.c user/errno.c
+
+$(INITRD_IMG): $(MKINITRD) $(USER_ELF) $(ECHO_ELF) $(SH_ELF) $(CAT_ELF) $(LS_ELF) $(MKDIR_ELF) $(RM_ELF)
+ @./$(MKINITRD) $(INITRD_IMG) $(USER_ELF):bin/init.elf $(ECHO_ELF):bin/echo.elf $(SH_ELF):bin/sh $(CAT_ELF):bin/cat $(LS_ELF):bin/ls $(MKDIR_ELF):bin/mkdir $(RM_ELF):bin/rm
run: iso
@rm -f serial.log qemu.log
--- /dev/null
+/* AdrOS cat utility */
+#include <stdint.h>
+#include "user_errno.h"
+
+enum {
+ SYSCALL_WRITE = 1,
+ SYSCALL_EXIT = 2,
+ SYSCALL_OPEN = 4,
+ SYSCALL_READ = 5,
+ SYSCALL_CLOSE = 6,
+};
+
+static int sys_write(int fd, const void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_WRITE), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_read(int fd, void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_READ), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_open(const char* path, int flags) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_OPEN), "b"(path), "c"(flags) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_close(int fd) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_CLOSE), "b"(fd) : "memory");
+ return __syscall_fix(ret);
+}
+
+static __attribute__((noreturn)) void sys_exit(int code) {
+ __asm__ volatile("int $0x80" : : "a"(SYSCALL_EXIT), "b"(code) : "memory");
+ for (;;) __asm__ volatile("hlt");
+}
+
+static uint32_t slen(const char* s) {
+ uint32_t n = 0;
+ while (s && s[n]) n++;
+ return n;
+}
+
+static void wr(int fd, const char* s) {
+ (void)sys_write(fd, s, slen(s));
+}
+
+static void cat_fd(int fd) {
+ char buf[256];
+ int r;
+ while ((r = sys_read(fd, buf, sizeof(buf))) > 0) {
+ sys_write(1, buf, (uint32_t)r);
+ }
+}
+
+static void cat_main(uint32_t* sp0) {
+ uint32_t argc = sp0 ? sp0[0] : 0;
+ const char* const* argv = (const char* const*)(sp0 + 1);
+
+ if (argc <= 1) {
+ cat_fd(0);
+ sys_exit(0);
+ }
+
+ int rc = 0;
+ for (uint32_t i = 1; i < argc; i++) {
+ int fd = sys_open(argv[i], 0);
+ if (fd < 0) {
+ wr(2, "cat: ");
+ wr(2, argv[i]);
+ wr(2, ": No such file\n");
+ rc = 1;
+ continue;
+ }
+ cat_fd(fd);
+ sys_close(fd);
+ }
+ sys_exit(rc);
+}
+
+__attribute__((naked)) void _start(void) {
+ __asm__ volatile(
+ "mov %esp, %eax\n"
+ "push %eax\n"
+ "call cat_main\n"
+ "add $4, %esp\n"
+ "mov $0, %ebx\n"
+ "mov $2, %eax\n"
+ "int $0x80\n"
+ "hlt\n"
+ );
+}
--- /dev/null
+/* AdrOS ls utility */
+#include <stdint.h>
+#include "user_errno.h"
+
+enum {
+ SYSCALL_WRITE = 1,
+ SYSCALL_EXIT = 2,
+ SYSCALL_OPEN = 4,
+ SYSCALL_CLOSE = 6,
+ SYSCALL_GETDENTS = 30,
+};
+
+static int sys_write(int fd, const void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_WRITE), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_open(const char* path, int flags) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_OPEN), "b"(path), "c"(flags) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_close(int fd) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_CLOSE), "b"(fd) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_getdents(int fd, void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_GETDENTS), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static __attribute__((noreturn)) void sys_exit(int code) {
+ __asm__ volatile("int $0x80" : : "a"(SYSCALL_EXIT), "b"(code) : "memory");
+ for (;;) __asm__ volatile("hlt");
+}
+
+static uint32_t slen(const char* s) {
+ uint32_t n = 0;
+ while (s && s[n]) n++;
+ return n;
+}
+
+static void wr(int fd, const char* s) {
+ (void)sys_write(fd, s, slen(s));
+}
+
+struct dirent {
+ uint32_t d_ino;
+ uint16_t d_reclen;
+ uint8_t d_type;
+ char d_name[24];
+};
+
+static void ls_dir(const char* path) {
+ int fd = sys_open(path, 0);
+ if (fd < 0) {
+ wr(2, "ls: cannot open ");
+ wr(2, path);
+ wr(2, "\n");
+ return;
+ }
+
+ char buf[512];
+ int rc = sys_getdents(fd, buf, sizeof(buf));
+ if (rc > 0) {
+ uint32_t off = 0;
+ while (off + sizeof(struct dirent) <= (uint32_t)rc) {
+ struct dirent* d = (struct dirent*)(buf + off);
+ if (d->d_reclen == 0) break;
+ /* skip . and .. */
+ if (d->d_name[0] == '.' &&
+ (d->d_name[1] == 0 ||
+ (d->d_name[1] == '.' && d->d_name[2] == 0))) {
+ off += d->d_reclen;
+ continue;
+ }
+ wr(1, d->d_name);
+ wr(1, "\n");
+ off += d->d_reclen;
+ }
+ }
+
+ sys_close(fd);
+}
+
+static void ls_main(uint32_t* sp0) {
+ uint32_t argc = sp0 ? sp0[0] : 0;
+ const char* const* argv = (const char* const*)(sp0 + 1);
+
+ if (argc <= 1) {
+ ls_dir(".");
+ } else {
+ for (uint32_t i = 1; i < argc; i++) {
+ if (argc > 2) {
+ wr(1, argv[i]);
+ wr(1, ":\n");
+ }
+ ls_dir(argv[i]);
+ }
+ }
+ sys_exit(0);
+}
+
+__attribute__((naked)) void _start(void) {
+ __asm__ volatile(
+ "mov %esp, %eax\n"
+ "push %eax\n"
+ "call ls_main\n"
+ "add $4, %esp\n"
+ "mov $0, %ebx\n"
+ "mov $2, %eax\n"
+ "int $0x80\n"
+ "hlt\n"
+ );
+}
--- /dev/null
+/* AdrOS mkdir utility */
+#include <stdint.h>
+#include "user_errno.h"
+
+enum {
+ SYSCALL_WRITE = 1,
+ SYSCALL_EXIT = 2,
+ SYSCALL_MKDIR = 28,
+};
+
+static int sys_write(int fd, const void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_WRITE), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_mkdir(const char* path) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_MKDIR), "b"(path) : "memory");
+ return __syscall_fix(ret);
+}
+
+static __attribute__((noreturn)) void sys_exit(int code) {
+ __asm__ volatile("int $0x80" : : "a"(SYSCALL_EXIT), "b"(code) : "memory");
+ for (;;) __asm__ volatile("hlt");
+}
+
+static uint32_t slen(const char* s) {
+ uint32_t n = 0;
+ while (s && s[n]) n++;
+ return n;
+}
+
+static void wr(int fd, const char* s) {
+ (void)sys_write(fd, s, slen(s));
+}
+
+static void mkdir_main(uint32_t* sp0) {
+ uint32_t argc = sp0 ? sp0[0] : 0;
+ const char* const* argv = (const char* const*)(sp0 + 1);
+
+ if (argc <= 1) {
+ wr(2, "mkdir: missing operand\n");
+ sys_exit(1);
+ }
+
+ int rc = 0;
+ for (uint32_t i = 1; i < argc; i++) {
+ if (sys_mkdir(argv[i]) < 0) {
+ wr(2, "mkdir: cannot create '");
+ wr(2, argv[i]);
+ wr(2, "'\n");
+ rc = 1;
+ }
+ }
+ sys_exit(rc);
+}
+
+__attribute__((naked)) void _start(void) {
+ __asm__ volatile(
+ "mov %esp, %eax\n"
+ "push %eax\n"
+ "call mkdir_main\n"
+ "add $4, %esp\n"
+ "mov $0, %ebx\n"
+ "mov $2, %eax\n"
+ "int $0x80\n"
+ "hlt\n"
+ );
+}
--- /dev/null
+/* AdrOS rm utility */
+#include <stdint.h>
+#include "user_errno.h"
+
+enum {
+ SYSCALL_WRITE = 1,
+ SYSCALL_EXIT = 2,
+ SYSCALL_UNLINK = 29,
+ SYSCALL_RMDIR = 40,
+};
+
+static int sys_write(int fd, const void* buf, uint32_t len) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_WRITE), "b"(fd), "c"(buf), "d"(len) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_unlink(const char* path) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_UNLINK), "b"(path) : "memory");
+ return __syscall_fix(ret);
+}
+
+static int sys_rmdir(const char* path) {
+ int ret;
+ __asm__ volatile("int $0x80" : "=a"(ret)
+ : "a"(SYSCALL_RMDIR), "b"(path) : "memory");
+ return __syscall_fix(ret);
+}
+
+static __attribute__((noreturn)) void sys_exit(int code) {
+ __asm__ volatile("int $0x80" : : "a"(SYSCALL_EXIT), "b"(code) : "memory");
+ for (;;) __asm__ volatile("hlt");
+}
+
+static uint32_t slen(const char* s) {
+ uint32_t n = 0;
+ while (s && s[n]) n++;
+ return n;
+}
+
+static void wr(int fd, const char* s) {
+ (void)sys_write(fd, s, slen(s));
+}
+
+static int scmp(const char* a, const char* b) {
+ while (*a && *b && *a == *b) { a++; b++; }
+ return (unsigned char)*a - (unsigned char)*b;
+}
+
+static void rm_main(uint32_t* sp0) {
+ uint32_t argc = sp0 ? sp0[0] : 0;
+ const char* const* argv = (const char* const*)(sp0 + 1);
+
+ if (argc <= 1) {
+ wr(2, "rm: missing operand\n");
+ sys_exit(1);
+ }
+
+ int rflag = 0;
+ int rc = 0;
+ uint32_t start = 1;
+
+ if (argv[1] && (scmp(argv[1], "-r") == 0 || scmp(argv[1], "-rf") == 0 ||
+ scmp(argv[1], "-d") == 0)) {
+ rflag = 1;
+ start = 2;
+ }
+
+ for (uint32_t i = start; i < argc; i++) {
+ int r = sys_unlink(argv[i]);
+ if (r < 0 && rflag) {
+ r = sys_rmdir(argv[i]);
+ }
+ if (r < 0) {
+ wr(2, "rm: cannot remove '");
+ wr(2, argv[i]);
+ wr(2, "'\n");
+ rc = 1;
+ }
+ }
+ sys_exit(rc);
+}
+
+__attribute__((naked)) void _start(void) {
+ __asm__ volatile(
+ "mov %esp, %eax\n"
+ "push %eax\n"
+ "call rm_main\n"
+ "add $4, %esp\n"
+ "mov $0, %ebx\n"
+ "mov $2, %eax\n"
+ "int $0x80\n"
+ "hlt\n"
+ );
+}