From fde896f371513340b3ce79dfc950e932979a0906 Mon Sep 17 00:00:00 2001 From: StepanovPlaton Date: Wed, 4 Feb 2026 19:43:33 +0400 Subject: [PATCH] Hello world --- LICENSE | 8 ++++ src/.clang-format | 3 ++ src/.clangd | 2 + src/.gitignore | 9 +++++ src/Makefile | 5 +++ src/common.c | 97 +++++++++++++++++++++++++++++++++++++++++++++++ src/common.h | 35 +++++++++++++++++ src/kernel.c | 36 ++++++++++++++++++ src/kernel.h | 17 +++++++++ src/kernel.ld | 28 ++++++++++++++ src/run.bat | 4 ++ src/run.sh | 4 ++ 12 files changed, 248 insertions(+) create mode 100644 LICENSE create mode 100644 src/.clang-format create mode 100644 src/.clangd create mode 100644 src/.gitignore create mode 100644 src/Makefile create mode 100644 src/common.c create mode 100644 src/common.h create mode 100644 src/kernel.c create mode 100644 src/kernel.h create mode 100644 src/kernel.ld create mode 100644 src/run.bat create mode 100644 src/run.sh diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1b1ddd9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,8 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ \ No newline at end of file diff --git a/src/.clang-format b/src/.clang-format new file mode 100644 index 0000000..90c53c3 --- /dev/null +++ b/src/.clang-format @@ -0,0 +1,3 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +ColumnLimit: 80 \ No newline at end of file diff --git a/src/.clangd b/src/.clangd new file mode 100644 index 0000000..45e173e --- /dev/null +++ b/src/.clangd @@ -0,0 +1,2 @@ +CompileFlags: + Add: [-std=c11, -Wall, -Wextra, --target=riscv32, -ffreestanding, -nostdlib] \ No newline at end of file diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..1c68b20 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,9 @@ +/disk/* +!/disk/.gitkeep +*.map +*.tar +*.o +*.elf +*.bin +*.log +*.pcap \ No newline at end of file diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..409cadc --- /dev/null +++ b/src/Makefile @@ -0,0 +1,5 @@ +CC = clang +CFLAGS = -std=c11 -O2 -g3 -Wall -Wextra --target=riscv32 -ffreestanding -nostdlib + +kernel: + $(CC) $(CFLAGS) -Wl,-Tkernel.ld -Wl,-Map=kernel.map -o kernel.elf kernel.c common.c \ No newline at end of file diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..a137e26 --- /dev/null +++ b/src/common.c @@ -0,0 +1,97 @@ +#include "common.h" + +void putchar(char ch); + +void *memset(void *buf, char c, size_t n) { + uint8_t *p = (uint8_t *)buf; + while (n--) + *p++ = c; + return buf; +} + +void *memcpy(void *dst, const void *src, size_t n) { + uint8_t *d = (uint8_t *)dst; + const uint8_t *s = (const uint8_t *)src; + while (n--) + *d++ = *s++; + return dst; +} + +char *strcpy(char *dst, const char *src) { + char *d = dst; + while (*src) + *d++ = *src++; + *d = '\0'; + return dst; +} + +int strcmp(const char *s1, const char *s2) { + while (*s1 && *s2) { + if (*s1 != *s2) + break; + s1++; + s2++; + } + + return *(unsigned char *)s1 - *(unsigned char *)s2; +} + +void printf(const char *fmt, ...) { + va_list vargs; + va_start(vargs, fmt); + + while (*fmt) { + if (*fmt == '%') { + fmt++; + switch (*fmt) { + case '\0': + putchar('%'); + goto end; + case '%': + putchar('%'); + break; + case 's': { + const char *s = va_arg(vargs, const char *); + while (*s) { + putchar(*s); + s++; + } + break; + } + case 'd': { + int value = va_arg(vargs, int); + if (value < 0) { + putchar('-'); + value = -value; + } + + int divisor = 1; + while (value / divisor > 9) + divisor *= 10; + + while (divisor > 0) { + putchar('0' + value / divisor); + value %= divisor; + divisor /= 10; + } + + break; + } + case 'x': { + int value = va_arg(vargs, int); + for (int i = 7; i >= 0; i--) { + int nibble = (value >> (i * 4)) & 0xf; + putchar("0123456789abcdef"[nibble]); + } + } + } + } else { + putchar(*fmt); + } + + fmt++; + } + +end: + va_end(vargs); +} \ No newline at end of file diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..9327b59 --- /dev/null +++ b/src/common.h @@ -0,0 +1,35 @@ +#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, ...); \ No newline at end of file diff --git a/src/kernel.c b/src/kernel.c new file mode 100644 index 0000000..8334982 --- /dev/null +++ b/src/kernel.c @@ -0,0 +1,36 @@ +#include "kernel.h" + +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); } + +void kernel_main(void) { + memset(__bss, 0, (size_t)__bss_end - (size_t)__bss); + + PANIC("booted!"); + printf("unreachable here!\n"); +} + +__attribute__((section(".text.boot"))) __attribute__((naked)) void boot(void) { + __asm__ __volatile__("mv sp, %[stack_top]\n" + "j kernel_main\n" + : + : [stack_top] "r"(__stack_top)); +} \ No newline at end of file diff --git a/src/kernel.h b/src/kernel.h new file mode 100644 index 0000000..adbb4f0 --- /dev/null +++ b/src/kernel.h @@ -0,0 +1,17 @@ +#pragma once + +#include "common.h" + +extern char __bss[], __bss_end[], __stack_top[]; + +struct sbiret { + long error; + long value; +}; + +#define PANIC(fmt, ...) \ + do { \ + printf("PANIC: %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__); \ + while (1) { \ + } \ + } while (0) \ No newline at end of file diff --git a/src/kernel.ld b/src/kernel.ld new file mode 100644 index 0000000..f4b4a9a --- /dev/null +++ b/src/kernel.ld @@ -0,0 +1,28 @@ +ENTRY(boot) + +SECTIONS { + . = 0x80200000; + + .text :{ + KEEP(*(.text.boot)); + *(.text .text.*); + } + + .rodata : ALIGN(4) { + *(.rodata .rodata.*); + } + + .data : ALIGN(4) { + *(.data .data.*); + } + + .bss : ALIGN(4) { + __bss = .; + *(.bss .bss.* .sbss .sbss.*); + __bss_end = .; + } + + . = ALIGN(4); + . += 128 * 1024; /* 128KB */ + __stack_top = .; +} \ No newline at end of file diff --git a/src/run.bat b/src/run.bat new file mode 100644 index 0000000..eb99bd9 --- /dev/null +++ b/src/run.bat @@ -0,0 +1,4 @@ +@echo off +make kernel +cd /d "C:\Program Files\qemu" +qemu-system-riscv32.exe -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel %~dp0kernel.elf \ No newline at end of file diff --git a/src/run.sh b/src/run.sh new file mode 100644 index 0000000..ccbf846 --- /dev/null +++ b/src/run.sh @@ -0,0 +1,4 @@ +#!/bin/bash +set -xue + +qemu-system-riscv32 -machine virt -bios default -nographic -serial mon:stdio --no-reboot -kernel kernel.elf \ No newline at end of file