From ceb9471fed96f907e37a6ba031825c31167a8ff4 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Mon, 21 Apr 2025 16:45:28 -0400 Subject: update userland to compile --- user/lib/alloc.c | 15 +++++- user/lib/entry.S | 26 +++------- user/lib/fread.c | 65 +++++++++++++++++++++++ user/lib/fwrite.c | 57 ++++++++++++++++++++ user/lib/printf.c | 40 +------------- user/lib/spawn.c | 32 ------------ user/lib/syscall.S | 113 +++++++++------------------------------- user/lib/timetostr.c | 143 --------------------------------------------------- 8 files changed, 167 insertions(+), 324 deletions(-) create mode 100644 user/lib/fread.c create mode 100644 user/lib/fwrite.c delete mode 100644 user/lib/spawn.c delete mode 100644 user/lib/timetostr.c (limited to 'user/lib') diff --git a/user/lib/alloc.c b/user/lib/alloc.c index 49c762b..3d987d4 100644 --- a/user/lib/alloc.c +++ b/user/lib/alloc.c @@ -21,6 +21,19 @@ static const size_t header_len = sizeof(struct page_header); static struct page_header *start_header = NULL; static struct page_header *end_header = NULL; +static void *alloc_pages(size_t pages) +{ + (void)pages; + // TODO: impl + return NULL; +} + +static void free_pages(struct page_header *header) +{ + (void)header; + // TODO: impl +} + static struct page_header *get_header(void *ptr) { struct page_header *header = @@ -39,7 +52,6 @@ static void *alloc_new(size_t size) { size_t pages = ((size + header_len) / PAGE_SIZE) + 1; - // FIXME: use brk/sbrk void *addr = alloc_pages(pages); void *mem = (char *)addr + header_len; @@ -209,7 +221,6 @@ void free(void *ptr) header->next->prev = header->prev; if (header->prev) header->prev->next = header->next; - // FIXME: use brk/sbrk free_pages(header); } } diff --git a/user/lib/entry.S b/user/lib/entry.S index 87ad9c7..34390a0 100644 --- a/user/lib/entry.S +++ b/user/lib/entry.S @@ -1,25 +1,15 @@ -// -// user-level startup routine -// - .text .globl _start - .globl main - .globl exit + .extern main + .extern exit -// entry point - this is where the kernel starts us running + .section .text + .code64 _start: - // we immediately call main() call main - // if we come back from that, it means the user - // program didn't call exit(), in which case the - // value returned from main() is the exit status - - // push that value onto the stack and call exit() - subl $12, %esp - pushl %eax + subq $16, %rsp # ??? + pushq %rax call exit - // if we come back from that, something bad has - // happened, so we just lock up -1: jmp 1b +halt: + jmp halt diff --git a/user/lib/fread.c b/user/lib/fread.c new file mode 100644 index 0000000..f8d0ad8 --- /dev/null +++ b/user/lib/fread.c @@ -0,0 +1,65 @@ +#include +#include + +FILE *stdin = (void *)0; + +int getchar(void) +{ + return fgetc(stdin); +} + +int getc(FILE *stream) +{ + return fgetc(stream); +} + +int fgetc(FILE *stream) +{ + int c; + if (fread(&c, 1, 1, stream) < 1) + return EOF; + return c; +} + +char *gets(char *str) +{ + char *s = str; + while (1) { + char c = fgetc(stdin); + if (c == '\n' || c == EOF || c == '\0') + break; + *(str++) = c; + } + *str = '\0'; + return s; +} + +char *fgets(char *restrict str, int size, FILE *stream) +{ + if (size < 1) + return NULL; + + char *s = str; + while (size > 1) { + char c = fgetc(stream); + if (c == '\n' || c == EOF || c == '\0') + break; + *(str++) = c; + size--; + } + + *str = '\0'; + return s; +} + +size_t fread(void *restrict ptr, size_t size, size_t n, FILE *restrict stream) +{ + int fd = (uintptr_t)stream; + char *restrict buf = ptr; + + for (size_t i = 0; i < n; i++) + if (read(fd, buf + i * size, size) < 1) + return i; + + return n; +} diff --git a/user/lib/fwrite.c b/user/lib/fwrite.c new file mode 100644 index 0000000..aa828e0 --- /dev/null +++ b/user/lib/fwrite.c @@ -0,0 +1,57 @@ +#include +#include + +FILE *stdout = (void *)1; + +int putchar(int c) +{ + return putc(c, stdout); +} + +int putc(int c, FILE *stream) +{ + return fputc(c, stream); +} + +int fputc(int c, FILE *stream) +{ + if (fwrite(&c, 1, 1, stream) < 1) + return EOF; + return c; +} + +int puts(const char *str) +{ + int res; + res = fputs(str, stdout); + if (res == EOF) + return res; + res = fputc('\n', stdout); + if (res == EOF) + return res; + return 0; +} + +int fputs(const char *str, FILE *stream) +{ + int res; + while (*str) { + res = fputc(*str++, stream); + if (res == EOF) + return res; + } + return 0; +} + +size_t fwrite(const void *restrict ptr, size_t size, size_t n, + FILE *restrict stream) +{ + int fd = (uintptr_t)stream; + const char *restrict buf = ptr; + + for (size_t i = 0; i < n; i++) + if (write(fd, buf + i * size, size) < 1) + return i; + + return n; +} diff --git a/user/lib/printf.c b/user/lib/printf.c index 65d7f0f..e6abd09 100644 --- a/user/lib/printf.c +++ b/user/lib/printf.c @@ -7,6 +7,7 @@ #include #define PRINTF_NUMERIC_BUF_LEN 50 +#define PRINTF_BUFFER_LEN 256 typedef union { unsigned long long int u; @@ -620,42 +621,3 @@ int vfprintf(FILE *stream, const char *format, va_list args) do_printf(&ctx, args); return ctx.written_len; } - -int putchar(int c) -{ - return putc(c, stdout); -} - -int putc(int c, FILE *stream) -{ - return fputc(c, stream); -} - -int fputc(int c, FILE *stream) -{ - // TODO: a - return c; -} - -int puts(const char *str) -{ - int res; - res = fputs(str, stdout); - if (res == EOF) - return res; - res = fputc('\n', stdout); - if (res == EOF) - return res; - return 0; -} - -int fputs(const char *str, FILE *stream) -{ - int res; - while (*str) { - res = fputc(*str++, stream); - if (res == EOF) - return res; - } - return 0; -} diff --git a/user/lib/spawn.c b/user/lib/spawn.c deleted file mode 100644 index 78b1a53..0000000 --- a/user/lib/spawn.c +++ /dev/null @@ -1,32 +0,0 @@ -#include -#include -#include - -int wait(int32_t *status) -{ - return (waitpid(0, status)); -} - -int spawn(uint_t prog, char **args) -{ - int32_t pid; - - pid = fork(); - if (pid != 0) { - // failure, or we are the parent - return (pid); - } - - // we are the child - pid = getpid(); - - // child inherits parent's priority level - - exec(prog, args); - - // uh-oh.... - - fprintf(stderr, "Child %d exec() #%u failed\n", pid, prog); - - exit(EXIT_FAILURE); -} diff --git a/user/lib/syscall.S b/user/lib/syscall.S index 46fcb89..fc1ab93 100644 --- a/user/lib/syscall.S +++ b/user/lib/syscall.S @@ -1,93 +1,26 @@ -/** -** @file ulibs.S -** -** @author CSCI-452 class of 20245 -** -** @brief assembly-language user-level library functions -*/ - -#define ASM_SRC - -// get the system call codes - #include -/** -** System call stubs -** -** All have the same structure: -** -** move a code into EAX -** generate the interrupt -** return to the caller -** -** As these are simple "leaf" routines, we don't use -** the standard enter/leave method to set up a stack -** frame - that takes time, and we don't really need it. -** -** Could be modified to use the UNIX/Linux convention of -** having the syscall code set the 'C' flag to indicate that -** the value being returned in %EAX is an error code: -** -** ... -** int $VEC_SYSCALL -** jc set_errno -** ret -** ... -** -** .globl errno -** set_errno: -** movl %eax, errno -** movl $-1, %eax -** ret -*/ - -#define SYSCALL(name) \ - .globl name ; \ -name: ; \ - movl $SYS_##name, %eax ; \ - int $VEC_SYSCALL ; \ +.macro SYSCALL name num + .align 8 + .globl \name +\name: + movq $\num, %rax + int $VEC_SYSCALL ret - -/* -** "real" system calls -*/ - -SYSCALL(exit) -SYSCALL(waitpid) -SYSCALL(fork) -SYSCALL(exec) -SYSCALL(read) -SYSCALL(write) -SYSCALL(getpid) -SYSCALL(getppid) -SYSCALL(gettime) -SYSCALL(getprio) -SYSCALL(setprio) -SYSCALL(kill) -SYSCALL(sleep) - -/* -** This is a bogus system call; it's here so that we can test -** our handling of out-of-range syscall codes in the syscall ISR. -*/ -SYSCALL(bogus) - -/* -** Other library functions -*/ - -/** -** fake_exit() -** -** Dummy "startup" function -** -** calls exit(%eax) - serves as the "return to" code for -** main() functions, in case they don't call exit() themselves -*/ - - .globl fake_exit -fake_exit: - // alternate: could push a "fake exit" status - pushl %eax // termination status returned by main() - call exit // terminate this process +.endm + +SYSCALL exit SYS_exit +SYSCALL waitpid SYS_waitpid +SYSCALL fork SYS_fork +SYSCALL exec SYS_exec +SYSCALL read SYS_read +SYSCALL write SYS_write +SYSCALL getpid SYS_getpid +SYSCALL getppid SYS_getppid +SYSCALL gettime SYS_gettime +SYSCALL getprio SYS_getprio +SYSCALL setprio SYS_setprio +SYSCALL kill SYS_kill +SYSCALL sleep SYS_sleep +SYSCALL brk SYS_brk +SYSCALL sbrk SYS_sbrk diff --git a/user/lib/timetostr.c b/user/lib/timetostr.c deleted file mode 100644 index fa77362..0000000 --- a/user/lib/timetostr.c +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include - -static char *ABB_WEEKDAY[7] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" -}; - -static char *FULL_WEEKDAY[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturady" }; - -static char *ABB_MONTH[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - -static char *FULL_MONTH[12] = { - "January", "Feburary", "March", "April", "May", "June", - "July", "August", "September", "October", "November", "December" -}; - -static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) -{ - size_t digits = 1; - unsigned int x = num; - - while (x /= 10, x > 0) - digits++; - if (pad == 0) - pad = digits; - - for (size_t i = 0; i < pad; i++) { - size_t digit; - if (i >= digits) { - digit = 0; - } else { - digit = num % 10; - num /= 10; - } - - if (pad - i - 1 >= n) - continue; - buf[pad - i - 1] = '0' + digit; - } - - if (pad > n) - pad = n; - - return buf + pad; -} - -void timetostr(time_t *time, char *format, char *buf, size_t n) -{ - char *index = buf; - char c; - int space; - - while (c = *format++, space = (buf + n) - index, c != '\0' && space > 0) { - if (c != '%') { - *index++ = c; - continue; - } else { - c = *format++; - } - - switch (c) { - case '%': - *index++ = '%'; - break; - case 'a': - index = strncpy(index, ABB_WEEKDAY[time->wday], space); - break; - case 'A': - index = strncpy(index, FULL_WEEKDAY[time->wday], space); - break; - case 'b': - case 'h': - index = strncpy(index, ABB_MONTH[time->mon], space); - break; - case 'B': - index = strncpy(index, FULL_MONTH[time->mon], space); - break; - case 'C': - index = write_num(time->cen, 0, index, space); - break; - case 'd': - index = write_num(time->mday, 2, index, space); - break; - case 'H': - index = write_num(time->hour, 2, index, space); - break; - case 'I': - index = write_num((time->hour + 12) % 12 + 1, 2, index, space); - break; - case 'j': - index = write_num(time->yday, 3, index, space); - break; - case 'm': - index = write_num(time->mon + 1, 2, index, space); - break; - case 'M': - index = write_num(time->min, 2, index, space); - break; - case 'n': - *index++ = '\n'; - break; - case 'p': - index = strncpy(index, time->hour > 11 ? "PM" : "AM", space); - break; - case 'P': - index = strncpy(index, time->hour > 11 ? "pm" : "am", space); - break; - case 'q': - index = write_num((time->mon + 3) / 3, 0, index, space); - break; - case 'S': - index = write_num(time->sec, 2, index, space); - break; - case 't': - *index++ = '\t'; - break; - case 'u': - index = write_num(((time->wday + 1) % 7) + 1, 0, index, space); - break; - case 'w': - index = write_num(time->wday, 0, index, space); - break; - case 'y': - index = write_num(time->yn, 2, index, space); - break; - case 'Y': - index = write_num(time->year + 1900, 0, index, space); - break; - default: { - char b[3] = { '%', c, '\0' }; - index = strncpy(index, b, space); - break; - } - } - } - - if (space < 1) - buf[n - 1] = '\0'; - else - *index = '\0'; -} -- cgit v1.2.3-freya