diff options
author | Jon Santmyer <jon@jonsantmyer.com> | 2021-11-26 16:23:32 -0500 |
---|---|---|
committer | Jon Santmyer <jon@jonsantmyer.com> | 2021-11-26 16:23:32 -0500 |
commit | 8a929b4f450616790f6d43a3078a8c6925264aa2 (patch) | |
tree | 842638c2d7ff1b81d06440d0b35d5dcff52cc1b1 | |
parent | cfd5c05a4d13519c3d21390ccd7798838f4bf1b5 (diff) | |
download | modit-slim-8a929b4f450616790f6d43a3078a8c6925264aa2.tar.gz modit-slim-8a929b4f450616790f6d43a3078a8c6925264aa2.tar.bz2 modit-slim-8a929b4f450616790f6d43a3078a8c6925264aa2.zip |
add arg processing to ld; padding for printf; shell vfs
-rw-r--r-- | app/init/ird.c | 82 | ||||
-rw-r--r-- | app/init/ird.h | 56 | ||||
-rw-r--r-- | app/init/main.c | 2 | ||||
-rw-r--r-- | app/init/scheduler.c | 17 | ||||
-rw-r--r-- | app/init/scheduler.h | 2 | ||||
-rw-r--r-- | app/ld/main.c | 100 | ||||
-rw-r--r-- | app/vfs/Makefile | 12 | ||||
-rw-r--r-- | app/vfs/main.c | 7 | ||||
m--------- | kernel | 0 | ||||
-rw-r--r-- | lib/c/stdio/puts.c | 7 | ||||
-rw-r--r-- | lib/c/stdio/vsnprintf.c | 26 | ||||
-rw-r--r-- | root/include/vfs/vfs.h | 41 |
12 files changed, 300 insertions, 52 deletions
diff --git a/app/init/ird.c b/app/init/ird.c index f2f2a30..2de9ca2 100644 --- a/app/init/ird.c +++ b/app/init/ird.c @@ -1,29 +1,105 @@ #include "ird.h" +#include "scheduler.h" #include <sys/mem.h> +#include <sys/cid.h> #include <modit/syscall.h> #include <modit/task.h> #include <stdio.h> DEFN_SYSCALL(initrd, SYSCALL_INITRD_GET) -struct initrd_file *initrd_head = NULL; +struct initrd_file *initrd_files = NULL; +size_t initrd_filesz = 0; static uintptr_t tar_start; static uintptr_t tar_end; +static size_t +tar_fromoctal(char *s) +{ + size_t num = 0; + for(; *s; s++) { + num *= 8; + num += (*s) - '0'; + } + + return num; +} + +static void +tar_parse(uintptr_t addr) +{ + size_t blocks = 0; + size_t filei = 0; + struct tar_header *block = (struct tar_header*)addr; + + while(block->name[0] != 0) { + size_t filesz = tar_fromoctal(block->size); + size_t fileblocks = (filesz + (TAR_BLOCKSIZE - 1)) / TAR_BLOCKSIZE; + + blocks += fileblocks + 1; + initrd_filesz++; + block = (struct tar_header*)(addr + (blocks * TAR_BLOCKSIZE)); + } + + initrd_files = malloc(sizeof(struct initrd_file) * initrd_filesz); + block = (struct tar_header*)addr; + blocks = 0; + while(block->name[0] != 0) { + size_t filesz = tar_fromoctal(block->size); + size_t fileblocks = (filesz + (TAR_BLOCKSIZE - 1)) / TAR_BLOCKSIZE; + + initrd_files[filei].name = block->name; + initrd_files[filei].size = filesz; + initrd_files[filei].data = (char*)((uintptr_t)block + TAR_BLOCKSIZE); + + printf("FILE %-16s SIZE %8i bytes\n", block->name, filesz); + + blocks += fileblocks + 1; + filei++; + block = (struct tar_header*)(addr + (blocks * TAR_BLOCKSIZE)); + } +} + +struct initrd_file* +ird_get(const char *name) +{ + for(size_t i = 0; i < initrd_filesz; i++) { + if(!strcmp(name, initrd_files[i].name)) return &initrd_files[i]; + } + return NULL; +} + +static void +ird_spawn(const char *prg) +{ + struct initrd_file *ldfile = ird_get("bin/ld"); + struct initrd_file *prgfile = ird_get(prg); +} + void ird_setup(void) { uintptr_t irdp = 0; size_t irds = 0; - struct syscall_initrd_data data = { .phys = &irdp, .len = &irds }; + + //Detach ird server from init + cid_t icid = fork_ghost(); + if(icid != 0) { + scheduler_addctx(root, icid, 0); + return; + } + _syscall_initrd(&data); tar_end = MODIT_USER_STACK - 0x1000000; - tar_start = tar_end - irds; + tar_start = tar_end - (((irds / 0x1000) + 1) * 0x1000); for(uintptr_t i = 0; i < irds; i += 0x1000) { mmap(irdp + i, tar_start + i); } + + tar_parse(tar_start); + ird_spawn("bin/vfs"); } diff --git a/app/init/ird.h b/app/init/ird.h index aaa072c..9d0e3b9 100644 --- a/app/init/ird.h +++ b/app/init/ird.h @@ -1,7 +1,61 @@ #ifndef INIT_IRD_H #define INIT_IRD_H 1 -#include "modit/initrd.h" +#include <stdint.h> +#include <stddef.h> + +#define TAR_LINK_NORMAL '0' +#define TAR_LINK_HARD '1' +#define TAR_LINK_SYMB '2' + +#define USTAR_TYPE_NORMAL '0' +#define USTAR_TYPE_HARD '1' +#define USTAR_TYPE_SYMB '2' +#define USTAR_TYPE_CHR '3' +#define USTAR_TYPE_BLK '4' +#define USTAR_TYPE_DIR '5' +#define USTAR_TYPE_FIFO '6' +#define USTAR_TYPE_CONTIG '7' + +#define TAR_BLOCKSIZE 512 + +struct tar_header { + char name[100]; + char mode[8]; + char oid[8]; + char gid[8]; + char size[12]; + char lmt[12]; + char checksum[8]; + char link; + char linkname[100]; +}; + +struct ustar_header { + char name[100]; + char mode[8]; + char oid[8]; + char gid[8]; + char size[12]; + char lmt[12]; + char checksum[8]; + char type; + char linkname[100]; + char ustar[6]; + char ustarver[2]; + char oun[32]; + char ogn[32]; + char devmajor[8]; + char devminor[8]; + char prefix[155]; +}; + +struct initrd_file { + const char *name; + char *data; + size_t size; + char flags; +}; void ird_setup(void); diff --git a/app/init/main.c b/app/init/main.c index a091a5a..348557c 100644 --- a/app/init/main.c +++ b/app/init/main.c @@ -13,8 +13,8 @@ main(int argc, char **argv) { (void)argc; (void)argv; - rpcsrv_setup(); scheduler_setup(); + rpcsrv_setup(); ird_setup(); rpc_handle(false); diff --git a/app/init/scheduler.c b/app/init/scheduler.c index 90eae64..2486194 100644 --- a/app/init/scheduler.c +++ b/app/init/scheduler.c @@ -55,6 +55,7 @@ scheduler_addctx(pid_t pid, cid_t id, uint8_t p) new->next = parent->contexts; new->cid = id; new->priority = p; + new->scheduled = true; struct clnode *node = malloc(sizeof(struct clnode)); node->ctx = new; @@ -103,14 +104,14 @@ scheduler_loop(void) settimer(20); swapto(1); while(1) { - for(struct clnode *node = list_tail; node; node = node->next) { - struct context *ctx = node->ctx; - if(!ctx->scheduled) continue; - list_current = node; - - settimer(PROC_QUANTUM(ctx->priority)); - swapto(ctx->cid); - } + if(list_current == NULL) list_current = list_tail; + struct context *ctx = list_current->ctx; + list_current = list_current->next; + + if(!ctx->scheduled) continue; + + settimer(PROC_QUANTUM(ctx->priority)); + swapto(ctx->cid); //Sort by priority } } diff --git a/app/init/scheduler.h b/app/init/scheduler.h index 559fb56..7726251 100644 --- a/app/init/scheduler.h +++ b/app/init/scheduler.h @@ -1,7 +1,7 @@ #ifndef INIT_SCHEDULER_H #define INIT_SCHEDULER_H 1 -#define PROC_PRIORITY_MUL 10 +#define PROC_PRIORITY_MUL 5 #define PROC_QUANTUM(l) ((l + 1) * PROC_PRIORITY_MUL) #include <stdbool.h> diff --git a/app/ld/main.c b/app/ld/main.c index 8613a0c..dd00df4 100644 --- a/app/ld/main.c +++ b/app/ld/main.c @@ -4,10 +4,10 @@ #include <stddef.h> static struct stkpack { - char **argv; - char **envp; - char data[]; -} *stack_data; + char *argv; + char *envp; + char *program; +} stack_data; DEFN_SYSCALL(print, SYSCALL_PRINT) void prints(const char *s) @@ -45,33 +45,66 @@ memset(void *restrict dest, char b, size_t n) } int +strlen(const char *s) { + size_t l = 0; + while(s[l]) l++; + return l; +} + +int strcmp(char *a, char *b) { size_t i = 0; while(a[i] == b[i] && a[i] != 0) i++; return a[i] - b[i]; } +#define PUSH(s, v, l) \ + s -= l; \ + memcpy((void*)s, (void*)v, l) + +#define PUSHV(s, v) \ + s -= 8; \ + *((uintptr_t*)s) = (uintptr_t)v + void elf_run(uintptr_t entry) { - size_t argc = 0; - //if(stack_data->argv != NULL) - // while(stack_data->argv[argc++] != 0); - - asm volatile("movq %0, %%rdi; \ - movq %1, %%rsi; \ - movq %2, %%rdx; \ - jmp %3":: - "r"(stack_data->argv), - "r"(argc), - "r"(stack_data->envp), - "r"(entry): "rdi", "rsi", "rdx"); + //We need room to place the new program's stack. + //Because the program data is already used, we can recycle it + uintptr_t nstack = (uintptr_t)stack_data.program; + + //Place argv + uintptr_t argvl = nstack; + int argc; + for(const char *arg = stack_data.argv; *arg; arg += strlen(arg)) { + PUSHV(nstack, arg); + argc++; + } + + //Place envp + uintptr_t envpl = nstack; + for(const char *env = stack_data.envp; *env; env += strlen(env)) { + PUSHV(nstack, env); + } + + //Place argc, [argv], [envp], entry + PUSHV(nstack, argvl); + PUSHV(nstack, argc ); + PUSHV(nstack, envpl); + PUSHV(nstack, entry); + + asm volatile("\ + mov %0, %%rsp; \ + popq %%rax; \ + popq %%rdx; \ + popq %%rdi; \ + popq %%rsi; \ + jmp %%rax;":: "r"(nstack)); } void -elf_parse_exec() +elf_parse_exec(struct elf64_header *header) { - struct elf64_header *header = (struct elf64_header*)stack_data->data; struct elf64_program_header *phdrs = (struct elf64_program_header*)((uintptr_t)header + header->e_phoff); for(size_t i = 0; i < header->e_phnum; i++) { @@ -80,30 +113,43 @@ elf_parse_exec() alloc(phdr->p_vaddr, phdr->p_memsz); memset((void*)(phdr->p_vaddr), 0, phdr->p_memsz); - memcpy((void*)(phdr->p_vaddr), (void*)((uintptr_t)stack_data->data + phdr->p_offset), phdr->p_filesz); + memcpy((void*)(phdr->p_vaddr), (void*)((uintptr_t)header + phdr->p_offset), phdr->p_filesz); } elf_run(header->e_entry); } int -elf_parse(void) +elf_parse(struct elf64_header *header) { - struct elf64_header *header = (struct elf64_header*)stack_data->data; - if(header->e_type == ELF_ET_EXEC) { - elf_parse_exec(); + elf_parse_exec(header); } prints("Unable to execute unknown ELF type\n"); return -1; } int -main(struct stkpack *data) +main(char *data) { - stack_data = data; + char *argv = data; + char *envp = data; + char *program = data; + + //Loop through NULL-terminated args list + for(; *envp; envp += strlen(envp)) prints(envp); + envp++; + + //Loop through NULL-terminated envp list + program = envp; + for(; *program; program += strlen(program)) prints(program); + program++; + + stack_data.argv = argv; + stack_data.envp = envp; + stack_data.program = program; - struct elf64_header *header = (struct elf64_header*)stack_data->data; + struct elf64_header *header = (struct elf64_header*)stack_data.program; if(!ELF_HEADER_CHECK(header)) { prints("Passed file is not ELF\n"); @@ -125,5 +171,5 @@ main(struct stkpack *data) return -4; } - return elf_parse(); + return elf_parse(header); } diff --git a/app/vfs/Makefile b/app/vfs/Makefile new file mode 100644 index 0000000..a172a09 --- /dev/null +++ b/app/vfs/Makefile @@ -0,0 +1,12 @@ +CFILES := $(wildcard *.c) +CFILES += $(wildcard *.s) + +CC ?= gcc + +WARNS := -Wall -Wextra -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wrestrict -Wnull-dereference -Wdouble-promotion -Wshadow -Wcast-align +CFLAGS := $(WARNS) -static +OUT := vfs + +.PHONY: all +all: $(CFILES) + $(CC) $(CFLAGS) $(CFILES) -o $(IRDDIR)/bin/$(OUT) diff --git a/app/vfs/main.c b/app/vfs/main.c new file mode 100644 index 0000000..ab05a67 --- /dev/null +++ b/app/vfs/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int +main(int argc, char **argv) +{ + printf("Hello, World!\n"); +} diff --git a/kernel b/kernel -Subproject 6f895bf2b6609a9b98bf8b74a6f7d140f3ed588 +Subproject c070667252e6db6bde6cb6b1d96a0c5bbb52b43 diff --git a/lib/c/stdio/puts.c b/lib/c/stdio/puts.c new file mode 100644 index 0000000..55a3472 --- /dev/null +++ b/lib/c/stdio/puts.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int +puts(const char *s) +{ + return prints(s); +} diff --git a/lib/c/stdio/vsnprintf.c b/lib/c/stdio/vsnprintf.c index b5c6a15..edc437b 100644 --- a/lib/c/stdio/vsnprintf.c +++ b/lib/c/stdio/vsnprintf.c @@ -7,7 +7,7 @@ static int __vsnprintf_itoa(char *term, intmax_t val, int base) { int size = 0; - intmax_t dec = 1; + uintmax_t dec = 1; bool neg = false; if(val < 0) { val = 0 - val; @@ -48,14 +48,15 @@ vsnprintf( } c++; //Flags - bool alternate = false, zero = false, leftadj = false, spaced = false, sign = false; + bool alternate = false, zero = false, leftadj = false, sign = false; + char padchr = ' '; while(strchr("#0- +", *c) != NULL) { switch(*c) { case '#': alternate = true; break; - case '0': zero = true; break; + case '0': padchr = '0'; zero = true; break; case '-': leftadj = true; break; - case ' ': spaced = true; break; + case ' ': padchr = ' '; zero = false; break; case '+': sign = true; break; } c++; @@ -96,13 +97,13 @@ vsnprintf( intmax_t val = va_arg(ap, intmax_t); int pwidth = __vsnprintf_itoa(NULL, val, base); int bufwidth = pwidth > minwidth ? pwidth : minwidth; //Make sure intstr will fit in buffer + int leftdist = leftadj == false ? bufwidth - 1 : (zero ? bufwidth - 1 : pwidth - 1); //Horrible left-align shenanigans if(val < 0 || sign) bufwidth++; //Make room for sign char buffer[bufwidth]; - if(zero) memset(buffer, '0', bufwidth); - if(spaced) memset(buffer, ' ', bufwidth); + memset(buffer, padchr, bufwidth); if(val < 0 || sign) //Set sign at top of buffer buffer[0] = val > 0 ? '+' : '-'; - __vsnprintf_itoa(&buffer[bufwidth - 1], val, base); //Write intstr to buffer starting at end + __vsnprintf_itoa(&buffer[leftdist], val, base); //Write intstr to buffer starting at end if(upper) strupp(buffer); wrsize += __vsnprintf_copytill(&str[wrsize], buffer, bufwidth, size); //Copy until reaching either bufwidth or size size -= bufwidth; @@ -110,10 +111,13 @@ vsnprintf( case 's': { const char *val = va_arg(ap, const char*); int vallen = strlen(val) - 1; - char buffer[vallen]; - memcpy(buffer, val, vallen); - wrsize += __vsnprintf_copytill(&str[wrsize], buffer, vallen, size); - size -= vallen; + int bufwidth = vallen > minwidth ? vallen : minwidth; + int leftdist = leftadj ? 0 : bufwidth - vallen; + char buffer[bufwidth]; + memset(buffer, padchr, bufwidth); + memcpy(buffer + (leftdist), val, vallen); + wrsize += __vsnprintf_copytill(&str[wrsize], buffer, bufwidth, size); + size -= bufwidth; } break; } } diff --git a/root/include/vfs/vfs.h b/root/include/vfs/vfs.h new file mode 100644 index 0000000..7bb0b18 --- /dev/null +++ b/root/include/vfs/vfs.h @@ -0,0 +1,41 @@ +#ifndef VFS_VFS_H +#define VFS_VFS_H 1 + +#include <sys/cid.h> +#include <rpc/rpc.h> + +#define VFS_FILE_TYPE_FILE 0 +#define VFS_FILE_TYPE_DIR 1 +#define VFS_FILE_TYPE_BLK 2 + +#define VFS_RPC_OPEN_ARGS "s" +#define VFS_RPC_OPEN_RET 'i' + +#define VFS_RPC_CLOSE_ARGS "i" +#define VFS_RPC_CLOSE_RET 'i' + +#define VFS_RPC_READ_ARGS "vi" +#define VFS_RPC_READ_RET 'i' + +#define VFS_RPC_WRITE_ARGS "vi" +#define VFS_RPC_WRITE_RET 'i' + +typedef struct vfs_file +{ + struct vfs_file *next; + struct vfs_file *children; + + const char *name; + char type; + char flags; + cid_t driver; + + RPCFUNC *open; + RPCFUNC *close; + RPCFUNC *read; + RPCFUNC *write; + + int dvri; +} vfs_file_t; + +#endif |