diff --git a/common.c b/common.c new file mode 100644 index 0000000..480d389 --- /dev/null +++ b/common.c @@ -0,0 +1,64 @@ +#include "common.h" + +void putchar(char ch); + +void printf(const char *fmt, ...) { + va_list vargs; + va_start(vargs, fmt); + + while (*fmt) { + if (*fmt == '%') { + fmt++; // Skip '%' + switch (*fmt) { // Read the next character + case '\0': // '%' at the end of the format string + putchar('%'); + goto end; + case '%': // Print '%' + putchar('%'); + break; + case 's': { // Print a NULL-termintated string + const char *s = va_arg(vargs, const char *); + while (*s) { + putchar(*s); + s++; + } + break; + } + case 'd': { // Print an integer in decimal + int value = va_arg(vargs, int); + unsigned magnitude = value; + if (value < 0) { + putchar('-'); + magnitude = -magnitude; + } + + unsigned divisor = 1; + while (magnitude / divisor > 9) + divisor *= 10; + + while (divisor > 0) { + putchar('0' + magnitude / divisor); + magnitude %= divisor; + divisor /= 10; + } + + break; + } + case 'x': { // Print an integer in hexademical + unsigned value = va_arg(vargs, unsigned); + for (int i = 7; i >= 0; i--) { + unsigned nibble = (value >> (i * 4)) & 0xf; + putchar("0123456789abcdef"[nibble]); + } + } + } + } else { + putchar(*fmt); + } + + fmt++; + } + +end: + va_end(vargs); +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..9adcc31 --- /dev/null +++ b/common.h @@ -0,0 +1,27 @@ +#pragma once + +typedef int bool; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef uint32_t size_t; +typedef uint32_t paddr_t; +typedef uint32_t vaddr_t; + +#define true 1 +#define false 0 +#define NULL ((void *) 0) +#define align_up(value, align) __builtin_align_up(value, align) +#define is_aligned(value, align) __builtin_is_aligned(value, align) +#define offsetof(type, member) __builtin_offsetof(type, member) +#define va_list __builtin_va_list +#define va_start __builtin_va_start +#define va_end __builtin_va_end +#define va_arg __builtin_va_arg + +void *memset(void *buf, char c, size_t n); +void *memcpy(void *dst, const void *src, size_t n); +char *strcpy(char *dst, const char *src); +int strcmp(const char *s1, const char *s2); +void printf(const char *fmt, ...); diff --git a/kernel.c b/kernel.c index 6abe1b7..0bc2384 100644 --- a/kernel.c +++ b/kernel.c @@ -1,28 +1,46 @@ -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef uint32_t size_t; +#include "kernel.h" +#include "common.h" extern char __bss[], __bss_end[], __stack_top[]; -void *memset(void *buf, char c, size_t n) { - uint8_t *p = (uint8_t *) buf; - while (n--) - *p++ = c; - return buf; +struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4, + long arg5, long fid, long eid) { + register long a0 __asm__("a0") = arg0; + register long a1 __asm__("a1") = arg1; + register long a2 __asm__("a2") = arg2; + register long a3 __asm__("a3") = arg3; + register long a4 __asm__("a4") = arg4; + register long a5 __asm__("a5") = arg5; + register long a6 __asm__("a6") = fid; + register long a7 __asm__("a7") = eid; + + __asm__ __volatile__("ecall" + : "=r"(a0), "=r"(a1) + : "r"(a0), "r"(a1), "r"(a2), "r"(a3), "r"(a4), "r"(a5), + "r"(a6), "r"(a7) + : "memory"); + return (struct sbiret){.error = a0, .value = a1}; +} + +void putchar(char ch) { + sbi_call(ch, 0, 0, 0, 0, 0, 0, 1 /* Console Putchar */); } void kernel_main(void) { - memset(__bss, 0, (size_t) __bss_end - (size_t) __bss); - - for (;;); + printf("\n\nHello %s\n", "RETARD!"); + printf("60 + 9 = %d, %x\n", 60 + 9, 0x1234abcd); + + for (;;) { + __asm__ __volatile__("wfi"); + } } __attribute__((section(".text.boot"))) __attribute__((naked)) void boot(void) { __asm__ __volatile__( - "mv sp, %[stack_top]\n" // Set stacker point - "j kernel_main\n" // Jump to the kernel function + "mv sp, %[stack_top]\n" // Set the stack pointer + "j kernel_main\n" // Jump to the kernel main function : : [stack_top] "r" (__stack_top) // Pass the stack top address as %[stack_top] ); diff --git a/kernel.h b/kernel.h new file mode 100644 index 0000000..4faa208 --- /dev/null +++ b/kernel.h @@ -0,0 +1,6 @@ +#pragma once + +struct sbiret { + long error; + long value; +}; diff --git a/run.sh b/run.sh index ad42e23..e312578 100755 --- a/run.sh +++ b/run.sh @@ -10,7 +10,7 @@ CFLAGS="-std=c11 -O2 -g3 -Wall -Wextra --target=riscv32-unknown-elf -fno-stack-p # Build the kernel $CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \ - kernel.c + kernel.c common.c # Start QEMU $QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \