os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 5a64354c094e9837ed559da68e658f2a57e8ceda
parent 99c9584644ea4f42aaac7386db08dfde7f89f903
Author: erai <erai@omiltem.net>
Date:   Mon, 27 May 2024 11:03:02 -0400

embed initramfs

Diffstat:
M.gitignore | 2++
Mas.c | 35+++++++++++++++++++++++++++++++++++
Mbootstrap.sh | 62+++++---------------------------------------------------------
Abuild.sh | 31+++++++++++++++++++++++++++++++
Mcc1.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Minit | 3+--
Mkernel.c | 6++++++
Mlib.c | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amkdir.c | 15+++++++++++++++
Amv.c | 9+++++++++
Mrm.c | 4+++-
Msyscall.c | 8++++++++
Mvi.c | 8++++++++
13 files changed, 226 insertions(+), 60 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -20,3 +20,5 @@ sshd vi as initramfs +mv +mkdir diff --git a/as.c b/as.c @@ -323,6 +323,41 @@ emit_num(c: *assembler, x: int) { as_opr(c, OP_PUSHR, R_RDX); } +emit_blob(c: *assembler, s: *byte, n: int) { + var a: *label; + var b: *label; + var i: int; + + a = mklabel(c); + b = mklabel(c); + + as_jmp(c, OP_JMP, b); + + fixup_label(c, a); + + i = 0; + loop { + if i == n { + break; + } + as_emit(c, s[i]:int); + i = i + 1; + } + as_emit(c, 0); + + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + as_op(c, OP_NOP); + + fixup_label(c, b); + emit_ptr(c, a); +} + emit_str(c: *assembler, s: *byte) { var a: *label; var b: *label; diff --git a/bootstrap.sh b/bootstrap.sh @@ -1,66 +1,14 @@ #!/bin/sh LIBS="bufio.c lib.c alloc.c syscall.c" -SOURCES="cc1.c type.c parse1.c lex1.c as.c $LIBS" -GENLEX_SOURCES="genlex.c $LIBS" +SOURCES="cc1.c type.c parse1.c lex1.c as.c" -./cc1 $SOURCES -o cc0 || gcc -Wall -Wextra -Wno-unused -pedantic -std=c99 ./cc0.c -o cc0 || exit 1 +gcc -Wall -Wextra -Wno-unused -pedantic -std=c99 ./cc0.c -o cc0 -./cc0 $SOURCES -o cc1 || exit 1 +./cc0 ${LIBS} ${SOURCES} -o cc1 -./cc1 $SOURCES -o cc2 || exit 1 +./cc1 ${LIBS} ${SOURCES} -o cc2 cmp cc1 cc2 || echo mismatch -./cc1 $GENLEX_SOURCES -o genlex || exit 1 -./genlex < cc3.l > lex3.c || exit 1 - -./cc1 $LIBS echo.c -o echo || exit 1 -./cc1 $LIBS cmp.c -o cmp || exit 1 -./cc1 $LIBS rm.c -o rm || exit 1 -./cc1 $LIBS ls.c -o ls || exit 1 -./cc1 $LIBS cpio.c -o cpio || exit 1 -./cc1 $LIBS sh.c -o sh || exit 1 -./cc1 $LIBS sshd.c -o sshd || exit 1 -./cc1 $LIBS vi.c -o vi || exit 1 - -{ - echo pxe.asm - echo chacha20.c - echo poly1305.c - echo sha256.c - echo sha512.c - echo ed25519.c - echo bootstrap.sh - echo bufio.c - echo lib.c - echo alloc.c - echo syscall.c - echo cc1.c - echo type.c - echo parse1.c - echo lex1.c - echo as.c - echo genlex.c - echo kernel.c - echo echo.c - echo echo - echo cmp.c - echo cmp - echo rm.c - echo rm - echo ls.c - echo ls - echo cpio.c - echo cpio - echo sh.c - echo sh - echo vi.c - echo vi - echo sshd.c - echo sshd - echo init - echo cc1 -} | ./cpio -o > initramfs || exit 1 - -./cc1 kernel.c -o kernel || exit 1 +sh ./build.sh diff --git a/build.sh b/build.sh @@ -0,0 +1,31 @@ +#!/sh + +LIBS="bufio.c lib.c alloc.c syscall.c" +CC="cc1.c type.c parse1.c lex1.c as.c" +GENLEX="genlex.c" +BOOT="pxe.asm" +SSHD="chacha20.c poly1305.c sha256.c sha512.c ed25519.c sshd.c" +KERNEL="kernel.c" +SHELL="echo.c cmp.c rm.c ls.c mv.c mkdir.c cpio.c vi.c sh.c" +BIN="echo cmp rm ls mv mkdir cpio sh vi sshd init cc1 cc2" +ALL="${LIBS} ${CC} ${GENLEX} ${BOOT} ${SSHD} ${KERNEL} ${SHELL} ${BIN}" + +./cc1 ${LIBS} ${CC} -o cc2 + +./cc2 ${LIBS} ${GENLEX} -o genlex +./genlex < cc3.l > lex3.c + +./cc2 ${LIBS} echo.c -o echo +./cc2 ${LIBS} cmp.c -o cmp +./cc2 ${LIBS} rm.c -o rm +./cc2 ${LIBS} mv.c -o mv +./cc2 ${LIBS} mkdir.c -o mkdir +./cc2 ${LIBS} ls.c -o ls +./cc2 ${LIBS} cpio.c -o cpio +./cc2 ${LIBS} sh.c -o sh +./cc2 ${LIBS} sshd.c -o sshd +./cc2 ${LIBS} vi.c -o vi + +for name in ${ALL}; do echo ${name}; done | ./cpio -o > initramfs + +./cc2 kernel.c -o kernel diff --git a/cc1.c b/cc1.c @@ -424,6 +424,36 @@ hoist_locals(c: *compiler, d: *decl, n: *node, offset: int): int { return offset; } +compile_include(c: *compiler, n: *node) { + var filename: *byte; + var fd: int; + var blob: *byte; + var len: int; + + if n.b.a.kind != N_STR { + die("non literal include"); + } + + filename = n.b.a.s; + + fd = open(filename, O_RDONLY, 0); + if fd < 0 { + die("failed to open include"); + } + + blob = readall(fd, &len, c.a); + + close(fd); + + as_opr(c.as, OP_POPR, R_RAX); + as_opr(c.as, OP_POPR, R_RDI); + as_opri64(c.as, OP_MOVABS, R_RAX, len); + as_modrm(c.as, OP_STORE, R_RAX, R_RDI, 0, 0, 0); + emit_blob(c.as, blob, len); + + free(c.a, blob); +} + // Translate an expression compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { var no: *label; @@ -497,6 +527,13 @@ compile_expr(c: *compiler, d: *decl, n: *node, rhs: int) { n.a.t = v.var_type; emit_load(c.as, n.a.t); emit_call(c.as, count_args(c, n.a.t.arg)); + } else if !strcmp(n.a.s, "_include") { + v = find(c, n.a.s, 0:*byte, 0); + if (!v || !v.func_defined) { + cdie(c, "no such function"); + } + n.a.t = v.func_type; + compile_include(c, n); } else { v = find(c, n.a.s, 0:*byte, 0); if (!v || !v.func_defined) { @@ -1578,6 +1615,15 @@ main(argc: int, argv: **byte, envp: **byte) { emit_ret(c.as); } + d = find(c, "_include", 0:*byte, 1); + if (d.func_defined && !d.func_label.fixed) { + fixup_label(c.as, d.func_label); + emit_preamble(c.as, 0, 0); + as_op(c.as, OP_UD2); + as_opr(c.as, OP_PUSHR, R_RAX); + emit_ret(c.as); + } + d = find(c, "ud2", 0:*byte, 1); if (d.func_defined && !d.func_label.fixed) { fixup_label(c.as, d.func_label); diff --git a/init b/init @@ -1,2 +1 @@ -#!/sh -/sshd +#!/sshd diff --git a/kernel.c b/kernel.c @@ -44,6 +44,8 @@ invlpg(x: int); _isr0(); _ssr0(); +_include(name: *byte, len: *int): *byte; + _rgs(x: int): int; struct regs { @@ -3589,6 +3591,10 @@ _ustart() { } } +initramfs(len: *int): *byte { + return _include("initramfs", len); +} + task_user(t: *task) { var r: regs; bzero((&r):*byte, sizeof(r)); diff --git a/lib.c b/lib.c @@ -37,6 +37,19 @@ strcmp(a: *byte, b: *byte): int { } } +fdgetc(fd: int): int { + var b: byte; + var ret: int; + ret = read(fd, &b, 1); + if (ret == 1) { + return b:int; + } else if (ret == 0) { + return -1; + } else { + exit(3); + } +} + fdputc(fd: int, ch: int) { var b: byte; var ret: int; @@ -341,3 +354,47 @@ assert(x: int, msg: *byte) { die(msg); } } + +readall(fd: int, len: *int, a: *alloc): *byte { + var buf: *byte; + var tmp: *byte; + var cap: int; + var newcap: int; + var ret: int; + var n: int; + + cap = 0; + n = 0; + + loop { + if n == cap { + if cap == 0 { + newcap = 4096; + } else { + newcap = cap * 2; + } + + tmp = alloc(a, newcap); + memcpy(tmp, buf, n); + free(a, buf); + buf = tmp; + cap = newcap; + } + + ret = read(fd, &buf[n], cap - n); + + if ret < 0 { + die("readall failed"); + } + + if ret == 0 { + break; + } + + n = n + ret; + } + + *len = n; + + return buf; +} diff --git a/mkdir.c b/mkdir.c @@ -0,0 +1,15 @@ +main(argc: int, argv: **byte, envp: **byte) { + var i: int; + i = 1; + loop { + if i >= argc { + return; + } + + if mkdir(argv[i]) != 0 { + die("mkdir failed"); + } + + i = i + 1; + } +} diff --git a/mv.c b/mv.c @@ -0,0 +1,9 @@ +main(argc: int, argv: **byte, envp: **byte) { + if argc != 3 { + die("usage: mv [src] [dest]"); + } + + if rename(argv[1], argv[2]) != 0 { + die("mv failed"); + } +} diff --git a/rm.c b/rm.c @@ -6,7 +6,9 @@ main(argc: int, argv: **byte, envp: **byte) { return; } - unlink(argv[i]); + if unlink(argv[i]) != 0 { + die("rm failed"); + } i = i + 1; } diff --git a/syscall.c b/syscall.c @@ -86,6 +86,14 @@ wait(pid: int, status: *int, flags: int): int { return syscall(61, pid, status:int, flags, 0, 0, 0); } +rename(oldname: *byte, newname: *byte): int { + return syscall(82, oldname: int, newname: int, 0, 0, 0, 0); +} + +mkdir(name: *byte): int { + return syscall(83, name: int, 0, 0, 0, 0, 0); +} + unlink(name: *byte): int { return syscall(87, name: int, 0, 0, 0, 0, 0); } diff --git a/vi.c b/vi.c @@ -1,2 +1,10 @@ main(argc: int, argv: **byte, envp: **byte) { + // normal mode + // insert mode + // line numbers + // line wrap + // read file + // write file + // delete + // h j k l }