basic types and memory operations
This commit is contained in:
64
common.c
Normal file
64
common.c
Normal file
@@ -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);
|
||||||
|
}
|
27
common.h
Normal file
27
common.h
Normal file
@@ -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, ...);
|
42
kernel.c
42
kernel.c
@@ -1,28 +1,46 @@
|
|||||||
typedef unsigned char uint8_t;
|
#include "kernel.h"
|
||||||
typedef unsigned int uint32_t;
|
#include "common.h"
|
||||||
typedef uint32_t size_t;
|
|
||||||
|
|
||||||
extern char __bss[], __bss_end[], __stack_top[];
|
extern char __bss[], __bss_end[], __stack_top[];
|
||||||
|
|
||||||
void *memset(void *buf, char c, size_t n) {
|
struct sbiret sbi_call(long arg0, long arg1, long arg2, long arg3, long arg4,
|
||||||
uint8_t *p = (uint8_t *) buf;
|
long arg5, long fid, long eid) {
|
||||||
while (n--)
|
register long a0 __asm__("a0") = arg0;
|
||||||
*p++ = c;
|
register long a1 __asm__("a1") = arg1;
|
||||||
return buf;
|
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) {
|
void kernel_main(void) {
|
||||||
memset(__bss, 0, (size_t) __bss_end - (size_t) __bss);
|
printf("\n\nHello %s\n", "RETARD!");
|
||||||
|
printf("60 + 9 = %d, %x\n", 60 + 9, 0x1234abcd);
|
||||||
|
|
||||||
for (;;);
|
for (;;) {
|
||||||
|
__asm__ __volatile__("wfi");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((section(".text.boot")))
|
__attribute__((section(".text.boot")))
|
||||||
__attribute__((naked))
|
__attribute__((naked))
|
||||||
void boot(void) {
|
void boot(void) {
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
"mv sp, %[stack_top]\n" // Set stacker point
|
"mv sp, %[stack_top]\n" // Set the stack pointer
|
||||||
"j kernel_main\n" // Jump to the kernel function
|
"j kernel_main\n" // Jump to the kernel main function
|
||||||
:
|
:
|
||||||
: [stack_top] "r" (__stack_top) // Pass the stack top address as %[stack_top]
|
: [stack_top] "r" (__stack_top) // Pass the stack top address as %[stack_top]
|
||||||
);
|
);
|
||||||
|
6
kernel.h
Normal file
6
kernel.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct sbiret {
|
||||||
|
long error;
|
||||||
|
long value;
|
||||||
|
};
|
2
run.sh
2
run.sh
@@ -10,7 +10,7 @@ CFLAGS="-std=c11 -O2 -g3 -Wall -Wextra --target=riscv32-unknown-elf -fno-stack-p
|
|||||||
|
|
||||||
# Build the kernel
|
# Build the kernel
|
||||||
$CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \
|
$CC $CFLAGS -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf \
|
||||||
kernel.c
|
kernel.c common.c
|
||||||
|
|
||||||
# Start QEMU
|
# Start QEMU
|
||||||
$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \
|
$QEMU -machine virt -bios default -nographic -serial mon:stdio --no-reboot \
|
||||||
|
Reference in New Issue
Block a user