commit 5a64354c094e9837ed559da68e658f2a57e8ceda
parent 99c9584644ea4f42aaac7386db08dfde7f89f903
Author: erai <erai@omiltem.net>
Date: Mon, 27 May 2024 11:03:02 -0400
embed initramfs
Diffstat:
M | .gitignore | | | 2 | ++ |
M | as.c | | | 35 | +++++++++++++++++++++++++++++++++++ |
M | bootstrap.sh | | | 62 | +++++--------------------------------------------------------- |
A | build.sh | | | 31 | +++++++++++++++++++++++++++++++ |
M | cc1.c | | | 46 | ++++++++++++++++++++++++++++++++++++++++++++++ |
M | init | | | 3 | +-- |
M | kernel.c | | | 6 | ++++++ |
M | lib.c | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | mkdir.c | | | 15 | +++++++++++++++ |
A | mv.c | | | 9 | +++++++++ |
M | rm.c | | | 4 | +++- |
M | syscall.c | | | 8 | ++++++++ |
M | vi.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
}