initial kernel
This commit is contained in:
109
.gitignore
vendored
Normal file
109
.gitignore
vendored
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/cmake,clion+all
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=cmake,clion+all
|
||||||
|
|
||||||
|
### CLion+all ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### CLion+all Patch ###
|
||||||
|
# Ignore everything but code style settings and run configurations
|
||||||
|
# that are supposed to be shared within teams.
|
||||||
|
|
||||||
|
.idea/*
|
||||||
|
|
||||||
|
!.idea/codeStyles
|
||||||
|
!.idea/runConfigurations
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
|
||||||
|
### CMake Patch ###
|
||||||
|
# External projects
|
||||||
|
*-prefix/
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/cmake,clion+all
|
||||||
19
CMakeLists.txt
Normal file
19
CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
project(yak)
|
||||||
|
cmake_minimum_required()
|
||||||
|
|
||||||
|
add_subdirectory(yak-kernel)
|
||||||
|
|
||||||
|
add_custom_target(boot-cdrom.iso
|
||||||
|
COMMAND xorriso -follow on -as mkisofs
|
||||||
|
-b limine-cd.bin
|
||||||
|
-no-emul-boot
|
||||||
|
-boot-load-size 4
|
||||||
|
-boot-info-table
|
||||||
|
--efi-boot
|
||||||
|
limine-cd-efi.bin
|
||||||
|
-efi-boot-part
|
||||||
|
--efi-boot-image
|
||||||
|
--protective-msdos-label
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/boot-cdrom
|
||||||
|
-o boot-cdrom.iso
|
||||||
|
DEPENDS yak.elf)
|
||||||
1
boot-cdrom/limine-cd-efi.bin
Symbolic link
1
boot-cdrom/limine-cd-efi.bin
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../limine/limine/limine-cd-efi.bin
|
||||||
1
boot-cdrom/limine-cd.bin
Symbolic link
1
boot-cdrom/limine-cd.bin
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../limine/limine/limine-cd.bin
|
||||||
10
boot-cdrom/limine.cfg
Normal file
10
boot-cdrom/limine.cfg
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Timeout in seconds that Limine will use before automatically booting.
|
||||||
|
TIMEOUT=3
|
||||||
|
|
||||||
|
# The entry name that will be displayed in the boot menu
|
||||||
|
:YAK
|
||||||
|
# Change the protocol line depending on the used protocol.
|
||||||
|
PROTOCOL=limine
|
||||||
|
|
||||||
|
# Path to the kernel to boot. boot:/// represents the partition on which limine.cfg is located.
|
||||||
|
KERNEL_PATH=boot:///yak.elf
|
||||||
1
boot-cdrom/limine.sys
Symbolic link
1
boot-cdrom/limine.sys
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../limine/limine/limine.sys
|
||||||
1
boot-cdrom/yak.elf
Symbolic link
1
boot-cdrom/yak.elf
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../cmake-build-debug-system-llvm/yak-kernel/yak.elf
|
||||||
1
limine/.gitignore
vendored
Normal file
1
limine/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
limine/
|
||||||
5
limine/fetch.sh
Normal file
5
limine/fetch.sh
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LIMINE_VERSION=v4.20230315.0
|
||||||
|
|
||||||
|
git clone https://github.com/limine-bootloader/limine.git --branch="${LIMINE_VERSION}-binary" --depth=1
|
||||||
1
limine/include/limine-hdd.h
Symbolic link
1
limine/include/limine-hdd.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../limine/limine-hdd.h
|
||||||
1
limine/include/limine.h
Symbolic link
1
limine/include/limine.h
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../limine/limine.h
|
||||||
5
run-qemu.sh
Executable file
5
run-qemu.sh
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ISO=${1}
|
||||||
|
|
||||||
|
qemu-system-x86_64 -bios /usr/share/ovmf/x64/OVMF.fd -cdrom "${ISO}" #-S -s -d guest_errors
|
||||||
27
yak-kernel/CMakeLists.txt
Normal file
27
yak-kernel/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
project(yak-kernel)
|
||||||
|
|
||||||
|
set(CMAKE_C_FLAGS "
|
||||||
|
-ffreestanding \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-stack-check \
|
||||||
|
-fno-lto \
|
||||||
|
-fno-pie \
|
||||||
|
-fno-pic \
|
||||||
|
-m64 \
|
||||||
|
-march=x86-64 \
|
||||||
|
-mabi=sysv \
|
||||||
|
-mno-80387 \
|
||||||
|
-mno-mmx \
|
||||||
|
-mno-sse \
|
||||||
|
-mno-sse2 \
|
||||||
|
-mno-red-zone \
|
||||||
|
-mcmodel=kernel")
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "
|
||||||
|
-nostdlib \
|
||||||
|
-static \
|
||||||
|
-z max-page-size=0x1000 \
|
||||||
|
-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.lds")
|
||||||
|
|
||||||
|
include_directories(../limine/include)
|
||||||
|
|
||||||
|
add_executable(yak.elf main.c)
|
||||||
57
yak-kernel/linker.lds
Normal file
57
yak-kernel/linker.lds
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* Tell the linker that we want an x86_64 ELF64 output file */
|
||||||
|
OUTPUT_FORMAT(elf64-x86-64)
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
|
||||||
|
/* We want the symbol _start to be our entry point */
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
/* Define the program headers we want so the bootloader gives us the right */
|
||||||
|
/* MMU permissions */
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
text PT_LOAD FLAGS((1 << 0) | (1 << 2)) ; /* Execute + Read */
|
||||||
|
rodata PT_LOAD FLAGS((1 << 2)) ; /* Read only */
|
||||||
|
data PT_LOAD FLAGS((1 << 1) | (1 << 2)) ; /* Write + Read */
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* We wanna be placed in the topmost 2GiB of the address space, for optimisations */
|
||||||
|
/* and because that is what the Limine spec mandates. */
|
||||||
|
/* Any address in this region will do, but often 0xffffffff80000000 is chosen as */
|
||||||
|
/* that is the beginning of the region. */
|
||||||
|
. = 0xffffffff80000000;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
*(.text .text.*)
|
||||||
|
} :text
|
||||||
|
|
||||||
|
/* Move to the next memory page for .rodata */
|
||||||
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata .rodata.*)
|
||||||
|
} :rodata
|
||||||
|
|
||||||
|
/* Move to the next memory page for .data */
|
||||||
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data .data.*)
|
||||||
|
} :data
|
||||||
|
|
||||||
|
/* NOTE: .bss needs to be the last thing mapped to :data, otherwise lots of */
|
||||||
|
/* unnecessary zeros will be written to the binary. */
|
||||||
|
/* If you need, for example, .init_array and .fini_array, those should be placed */
|
||||||
|
/* above this. */
|
||||||
|
.bss : {
|
||||||
|
*(COMMON)
|
||||||
|
*(.bss .bss.*)
|
||||||
|
} :data
|
||||||
|
|
||||||
|
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.eh_frame)
|
||||||
|
*(.note .note.*)
|
||||||
|
}
|
||||||
|
}
|
||||||
107
yak-kernel/main.c
Normal file
107
yak-kernel/main.c
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
// The Limine requests can be placed anywhere, but it is important that
|
||||||
|
// the compiler does not optimise them away, so, usually, they should
|
||||||
|
// be made volatile or equivalent.
|
||||||
|
|
||||||
|
static volatile struct limine_terminal_request terminal_request = {
|
||||||
|
.id = LIMINE_TERMINAL_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// GCC and Clang reserve the right to generate calls to the following
|
||||||
|
// 4 functions even if they are not directly called.
|
||||||
|
// Implement them as the C specification mandates.
|
||||||
|
// DO NOT remove or rename these functions, or stuff will eventually break!
|
||||||
|
// They CAN be moved to a different .c file.
|
||||||
|
|
||||||
|
void *memcpy(void *dest, const void *src, size_t n) {
|
||||||
|
uint8_t *pdest = (uint8_t *) dest;
|
||||||
|
const uint8_t *psrc = (const uint8_t *) src;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
pdest[i] = psrc[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memset(void *s, int c, size_t n) {
|
||||||
|
uint8_t *p = (uint8_t *) s;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
p[i] = (uint8_t) c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *memmove(void *dest, const void *src, size_t n) {
|
||||||
|
uint8_t *pdest = (uint8_t *) dest;
|
||||||
|
const uint8_t *psrc = (const uint8_t *) src;
|
||||||
|
|
||||||
|
if (src > dest) {
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
pdest[i] = psrc[i];
|
||||||
|
}
|
||||||
|
} else if (src < dest) {
|
||||||
|
for (size_t i = n; i > 0; i--) {
|
||||||
|
pdest[i - 1] = psrc[i - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||||
|
const uint8_t *p1 = (const uint8_t *) s1;
|
||||||
|
const uint8_t *p2 = (const uint8_t *) s2;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
if (p1[i] != p2[i]) {
|
||||||
|
return p1[i] < p2[i] ? -1 : 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Our quick and dirty strlen() implementation.
|
||||||
|
size_t strlen(const char *str) {
|
||||||
|
size_t ret = 0;
|
||||||
|
while (*str++) {
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Halt and catch fire function.
|
||||||
|
static void hcf(void) {
|
||||||
|
__asm__ ("cli");
|
||||||
|
for (;;) {
|
||||||
|
__asm__ ("hlt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The following will be our kernel's entry point.
|
||||||
|
// If renaming _start() to something else, make sure to change the
|
||||||
|
// linker script accordingly.
|
||||||
|
void _start(void) {
|
||||||
|
// Ensure we got a terminal
|
||||||
|
if (terminal_request.response == NULL
|
||||||
|
|| terminal_request.response->terminal_count < 1) {
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We should now be able to call the Limine terminal to print out
|
||||||
|
// a simple "Hello World" to screen.
|
||||||
|
const char *hello_msg = "Hello World";
|
||||||
|
|
||||||
|
struct limine_terminal *terminal = terminal_request.response->terminals[0];
|
||||||
|
terminal_request.response->write(terminal, hello_msg, strlen(hello_msg));
|
||||||
|
|
||||||
|
// We're done, just hang...
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user