+15
readme
+15
readme
+10
roadmap
+10
roadmap
+34
scripts/_config.sh
+34
scripts/_config.sh
···
1
+
#!/usr/bin/env sh
2
+
set -e
3
+
4
+
NMD_TOOLCHAIN="riscv64-elf-"
5
+
NMD_CC="gcc"
6
+
NMD_AS="as"
7
+
NMD_LD="ld"
8
+
9
+
NMD_INCLUDE="-Isrcs/"
10
+
11
+
NMD_KERNEL_CC_FLAGS="-Wall -Wextra -Werror -c -mcmodel=medany -ffreestanding $NMD_INCLUDE"
12
+
NMD_KERNEL_AS_FLAGS="-c"
13
+
NMD_KERNEL_LD_FLAGS="-nostdlib"
14
+
15
+
function nmd_echo
16
+
{
17
+
echo "$ $1"
18
+
$1
19
+
}
20
+
21
+
function nmd_cc()
22
+
{
23
+
nmd_echo "$NMD_TOOLCHAIN$NMD_CC $NMD_KERNEL_CC_FLAGS $NMD_ADD_KERNEL_CC_FLAGS $1 -o $2"
24
+
}
25
+
26
+
function nmd_as()
27
+
{
28
+
nmd_echo "$NMD_TOOLCHAIN$NMD_AS $NMD_KERNEL_AS_FLAGS $NMD_ADD_KERNEL_AS_FLAGS $1 -o $2"
29
+
}
30
+
31
+
function nmd_ld()
32
+
{
33
+
nmd_echo "$NMD_TOOLCHAIN$NMD_LD $NMD_KERNEL_LD_FLAGS $NMD_ADD_KERNEL_LD_FLAGS $1 -o $2"
34
+
}
+24
scripts/build-kernel.sh
+24
scripts/build-kernel.sh
···
1
+
#!/usr/bin/env sh
2
+
set -e
3
+
4
+
. scripts/_config.sh
5
+
6
+
mkdir -p build/kernel
7
+
8
+
echo ": kernel.c"
9
+
for f in `find srcs/kernel/ -name '*.c'`
10
+
do
11
+
ff=$(echo $f | tr '/' '_').o
12
+
nmd_cc $f build/kernel/$ff
13
+
done
14
+
15
+
echo ": entry.S"
16
+
nmd_as srcs/kernel/main/entry.S build/kernel/entry.o
17
+
18
+
echo ": linking"
19
+
NMD_ADD_KERNEL_LD_FLAGS="-T srcs/kernel/main/linker.ld" nmd_ld "build/kernel/*.o" build/kernel.elf
20
+
21
+
echo ": cleaning"
22
+
rm build/kernel/*.o
23
+
24
+
echo ": done"
+4
scripts/run-kernel-qemu.sh
+4
scripts/run-kernel-qemu.sh
+83
srcs/kernel/d/uart.c
+83
srcs/kernel/d/uart.c
···
1
+
#include <kernel/d/uart.h>
2
+
3
+
void uart_init(void)
4
+
{
5
+
volatile u8 *uart = (u8 *)UART_ADDR;
6
+
7
+
uart[3] = 3; /* set word length to 8 */
8
+
uart[2] = 1; /* enable FIFO */
9
+
uart[1] = 1; /* enable receiver buffer interrupts */
10
+
11
+
/* TODO: set baud rate here. QEMU on virt does this
12
+
automatically, but for bare metal we'll need to
13
+
do it ourselves. */
14
+
}
15
+
16
+
u8 uart_getr(void)
17
+
{
18
+
return *(u8 *)UART_ADDR;
19
+
}
20
+
21
+
u8 uart_getc(void)
22
+
{
23
+
u8 c = uart_getr();
24
+
*(u8 *)UART_ADDR = 0;
25
+
return c;
26
+
}
27
+
28
+
void uart_putc(u8 c)
29
+
{
30
+
*(u8 *)UART_ADDR = c;
31
+
}
32
+
33
+
void uart_puts(char *s)
34
+
{
35
+
while (*s != '\0')
36
+
{
37
+
uart_putc(*s);
38
+
s++;
39
+
}
40
+
}
41
+
42
+
void uart_putd(int d)
43
+
{
44
+
if (d < 0)
45
+
{
46
+
uart_putc('-');
47
+
d = -d;
48
+
}
49
+
char buf[32] = {0};
50
+
int i = 0;
51
+
while (d)
52
+
{
53
+
if (i > (int)sizeof(buf) - 1)
54
+
break; /* prevent overflow */
55
+
buf[i++] = '0' + (d%10);
56
+
d /= 10;
57
+
}
58
+
while (i)
59
+
{
60
+
uart_putc(buf[--i]);
61
+
}
62
+
}
63
+
64
+
void uart_putx(unsigned int x)
65
+
{
66
+
uart_puts("0x");
67
+
char buf[32] = {0};
68
+
int i = 0;
69
+
while (x)
70
+
{
71
+
if (i > (int)sizeof(buf) - 1)
72
+
break; /* prevent overflow */
73
+
if (x%16 >= 10)
74
+
buf[i++] = 'A' + (x%16)-10;
75
+
else
76
+
buf[i++] = '0' + (x%16);
77
+
x /= 16;
78
+
}
79
+
while (i)
80
+
{
81
+
uart_putc(buf[--i]);
82
+
}
83
+
}
+18
srcs/kernel/d/uart.h
+18
srcs/kernel/d/uart.h
···
1
+
#ifndef __nkern_uart__
2
+
#define __nkern_uart__
3
+
4
+
#include <kernel/nint.h>
5
+
6
+
#ifndef UART_ADDR
7
+
# define UART_ADDR (0x10000000)
8
+
#endif
9
+
10
+
void uart_init(void);
11
+
u8 uart_getr(void); /* raw get; does not clear UART */
12
+
u8 uart_getc(void); /* get character; clears UART */
13
+
void uart_putc(u8 c);
14
+
void uart_puts(char *s);
15
+
void uart_putd(int d);
16
+
void uart_putx(unsigned int x);
17
+
18
+
#endif
+34
srcs/kernel/main/entry.S
+34
srcs/kernel/main/entry.S
···
1
+
.section .init
2
+
3
+
.option norvc
4
+
5
+
.type start, @function
6
+
.global start
7
+
start:
8
+
.cfi_startproc
9
+
10
+
.option push
11
+
.option norelax
12
+
la gp, global_pointer
13
+
.option pop
14
+
15
+
csrw satp, zero /* reset satp */
16
+
17
+
la sp, stack_top /* setup stack */
18
+
19
+
/* clear bss */
20
+
la t5, bss_start
21
+
la t6, bss_end
22
+
bss_clear:
23
+
sd zero, (t5)
24
+
addi t5, t5, 8
25
+
bltu t5, t6, bss_clear
26
+
27
+
la t0, kmain
28
+
csrw mepc, t0
29
+
30
+
tail kmain /* jump to kernel */
31
+
32
+
.cfi_endproc
33
+
34
+
.end
+17
srcs/kernel/main/kmain.c
+17
srcs/kernel/main/kmain.c
···
1
+
#include <kernel/d/uart.h>
2
+
#include <kernel/panic.h>
3
+
#include <kernel/sys.h>
4
+
#include <kernel/nsh.h>
5
+
6
+
void kmain(void)
7
+
{
8
+
uart_init();
9
+
10
+
uart_puts("Hello, World!\r\n");
11
+
uart_putd(-42); uart_puts("\r\n");
12
+
uart_putx(0xB00B); uart_puts("\r\n");
13
+
14
+
nsh();
15
+
16
+
poweroff();
17
+
}
+31
srcs/kernel/main/linker.ld
+31
srcs/kernel/main/linker.ld
···
1
+
ENTRY(start);
2
+
3
+
. = 0x80000000;
4
+
5
+
SECTIONS
6
+
{
7
+
/* entry.S at the start of the binary */
8
+
.text : ALIGN(4K)
9
+
{
10
+
*(.init);
11
+
*(.text);
12
+
}
13
+
.bss : ALIGN(4K)
14
+
{
15
+
PROVIDE(bss_start = .);
16
+
*(.bss);
17
+
. += 4096;
18
+
PROVIDE(stack_top = .);
19
+
. += 4096;
20
+
PROVIDE(global_pointer = .);
21
+
PROVIDE(bss_end = .);
22
+
}
23
+
.rodata : ALIGN(4K)
24
+
{
25
+
*(.rodata);
26
+
}
27
+
.data : ALIGN(4K)
28
+
{
29
+
*(.data);
30
+
}
31
+
}
+20
srcs/kernel/mem.c
+20
srcs/kernel/mem.c
···
1
+
#include <kernel/mem.h>
2
+
#include <kernel/nint.h>
3
+
4
+
void *memcpy(void *dest, void *src, size_t n);
5
+
6
+
void *memmove(void *dest, void *src, size_t n);
7
+
8
+
void *memset(void *s, int c, size_t n)
9
+
{
10
+
u8 *ps = s;
11
+
while (n)
12
+
{
13
+
*ps = c;
14
+
ps++;
15
+
n--;
16
+
}
17
+
return s;
18
+
}
19
+
20
+
int memcmp(void *s1, void *s2, size_t n);
+12
srcs/kernel/mem.h
+12
srcs/kernel/mem.h
···
1
+
#ifndef __nkern_mem__
2
+
#define __nkern_mem__
3
+
4
+
#include <kernel/nint.h>
5
+
#include <stddef.h>
6
+
7
+
void *memcpy(void *dest, void *src, size_t n);
8
+
void *memmove(void *dest, void *src, size_t n);
9
+
void *memset(void *s, int c, size_t n);
10
+
int memcmp(void *s1, void *s2, size_t n);
11
+
12
+
#endif
+16
srcs/kernel/nint.h
+16
srcs/kernel/nint.h
···
1
+
#ifndef __nlibc_nint__
2
+
#define __nlibc_nint__
3
+
4
+
#include <stdint.h>
5
+
6
+
typedef int8_t i8;
7
+
typedef int16_t i16;
8
+
typedef int32_t i32;
9
+
typedef int64_t i64;
10
+
11
+
typedef uint8_t u8;
12
+
typedef uint16_t u16;
13
+
typedef uint32_t u32;
14
+
typedef uint64_t u64;
15
+
16
+
#endif
+62
srcs/kernel/nsh.c
+62
srcs/kernel/nsh.c
···
1
+
#include <kernel/nsh.h>
2
+
#include <kernel/d/uart.h>
3
+
#include <kernel/mem.h>
4
+
5
+
#define PROMPT "/ "
6
+
7
+
static void nsh_exec(char *cmd)
8
+
{
9
+
uart_puts("-> ");
10
+
uart_puts(cmd);
11
+
uart_puts("\r\n");
12
+
}
13
+
14
+
static int nsh_read(char *buf, int buflen)
15
+
{
16
+
static int i = 0;
17
+
18
+
uart_puts(PROMPT);
19
+
u8 ch = 0;
20
+
while (1)
21
+
{
22
+
ch = uart_getc();
23
+
switch (ch)
24
+
{
25
+
case 13: /* enter */
26
+
uart_puts("\r\n");
27
+
nsh_exec(buf);
28
+
memset(buf, 0, buflen - 1);
29
+
i = 0;
30
+
return 1;
31
+
case 3: /* ctrl-c */
32
+
uart_puts("\r\n");
33
+
memset(buf, 0, buflen - 1);
34
+
i = 0;
35
+
return 1;
36
+
case 4: /* ctrl-d */
37
+
uart_puts("\r\n");
38
+
return 0;
39
+
default:
40
+
buf[i++] = ch;
41
+
uart_putc(ch);
42
+
break;
43
+
}
44
+
}
45
+
46
+
return 1;
47
+
}
48
+
49
+
void nsh(void)
50
+
{
51
+
#define BUFLEN (1024)
52
+
char buf[BUFLEN];
53
+
memset(buf, 0, BUFLEN - 1);
54
+
55
+
while (1)
56
+
{
57
+
if (!nsh_read(&buf[0], BUFLEN))
58
+
{
59
+
break;
60
+
}
61
+
}
62
+
}
+6
srcs/kernel/nsh.h
+6
srcs/kernel/nsh.h
+10
srcs/kernel/panic.c
+10
srcs/kernel/panic.c
+6
srcs/kernel/panic.h
+6
srcs/kernel/panic.h
+14
srcs/kernel/sys.c
+14
srcs/kernel/sys.c