mirror of
https://github.com/johndoe6345789/MetalOS.git
synced 2026-04-24 13:45:02 +00:00
Add CMake, Ninja, and Conan support with kernel modules (GDT, interrupts)
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
20
.gitignore
vendored
20
.gitignore
vendored
@@ -20,6 +20,26 @@ build/
|
||||
bootloader/build/
|
||||
kernel/build/
|
||||
|
||||
# CMake
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
cmake-build-*/
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps/
|
||||
|
||||
# Ninja
|
||||
.ninja_deps
|
||||
.ninja_log
|
||||
|
||||
# Conan
|
||||
conan.lock
|
||||
conaninfo.txt
|
||||
conanbuildinfo.*
|
||||
graph_info.json
|
||||
|
||||
# Test binaries
|
||||
tests/unit/test_*
|
||||
!tests/unit/*.c
|
||||
|
||||
147
CMakeLists.txt
Normal file
147
CMakeLists.txt
Normal file
@@ -0,0 +1,147 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(MetalOS
|
||||
VERSION 0.1.0
|
||||
DESCRIPTION "Minimal OS for QT6 on AMD64 + RX 6600"
|
||||
LANGUAGES C CXX ASM_NASM
|
||||
)
|
||||
|
||||
# Enable assembly with NASM
|
||||
enable_language(ASM_NASM)
|
||||
|
||||
# Set C standard
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_C_STANDARD_REQUIRED ON)
|
||||
|
||||
# Set C++ standard (for QT6 app later)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Build type
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
endif()
|
||||
|
||||
# Output directories
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||
|
||||
# Platform-specific flags
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
||||
|
||||
# Global compile options for bare metal
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wextra
|
||||
-Werror
|
||||
-ffreestanding
|
||||
-fno-stack-protector
|
||||
-mno-red-zone
|
||||
)
|
||||
|
||||
# NASM flags for assembly files
|
||||
set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64)
|
||||
set(CMAKE_ASM_NASM_COMPILE_OBJECT "<CMAKE_ASM_NASM_COMPILER> <INCLUDES> <FLAGS> -f ${CMAKE_ASM_NASM_OBJECT_FORMAT} -o <OBJECT> <SOURCE>")
|
||||
|
||||
# Add subdirectories
|
||||
add_subdirectory(bootloader)
|
||||
add_subdirectory(kernel)
|
||||
add_subdirectory(userspace)
|
||||
|
||||
# Testing
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
|
||||
# Custom target to create bootable image
|
||||
add_custom_target(image
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/scripts/create_image.sh
|
||||
DEPENDS bootloader kernel
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMENT "Creating bootable disk image"
|
||||
)
|
||||
|
||||
# QEMU targets for testing
|
||||
set(QEMU_DISPLAY "none" CACHE STRING "QEMU display mode (none, gtk, sdl)")
|
||||
|
||||
# Find OVMF firmware
|
||||
find_file(OVMF_FIRMWARE
|
||||
NAMES OVMF_CODE.fd OVMF.fd ovmf-x86_64.bin
|
||||
PATHS
|
||||
/usr/share/OVMF
|
||||
/usr/share/ovmf
|
||||
/usr/share/edk2-ovmf/x64
|
||||
/usr/share/qemu
|
||||
DOC "UEFI firmware for QEMU"
|
||||
)
|
||||
|
||||
if(OVMF_FIRMWARE)
|
||||
message(STATUS "Found OVMF firmware: ${OVMF_FIRMWARE}")
|
||||
|
||||
# QEMU run target
|
||||
add_custom_target(qemu
|
||||
COMMAND qemu-system-x86_64
|
||||
-drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE}
|
||||
-drive format=raw,file=${CMAKE_BINARY_DIR}/metalos.img
|
||||
-m 512M
|
||||
-serial stdio
|
||||
-display ${QEMU_DISPLAY}
|
||||
-net none
|
||||
DEPENDS image
|
||||
COMMENT "Running MetalOS in QEMU with UEFI"
|
||||
)
|
||||
|
||||
# QEMU debug target
|
||||
add_custom_target(qemu-debug
|
||||
COMMAND qemu-system-x86_64
|
||||
-drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE}
|
||||
-drive format=raw,file=${CMAKE_BINARY_DIR}/metalos.img
|
||||
-m 512M
|
||||
-serial stdio
|
||||
-display ${QEMU_DISPLAY}
|
||||
-net none
|
||||
-d int,cpu_reset
|
||||
DEPENDS image
|
||||
COMMENT "Running MetalOS in QEMU with debug output"
|
||||
)
|
||||
|
||||
# QEMU GDB target
|
||||
add_custom_target(qemu-gdb
|
||||
COMMAND qemu-system-x86_64
|
||||
-drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE}
|
||||
-drive format=raw,file=${CMAKE_BINARY_DIR}/metalos.img
|
||||
-m 512M
|
||||
-serial stdio
|
||||
-display ${QEMU_DISPLAY}
|
||||
-net none
|
||||
-s -S
|
||||
DEPENDS image
|
||||
COMMENT "Running MetalOS in QEMU with GDB server on port 1234"
|
||||
)
|
||||
|
||||
# QEMU UEFI test (no OS image)
|
||||
add_custom_target(qemu-uefi-test
|
||||
COMMAND qemu-system-x86_64
|
||||
-drive if=pflash,format=raw,readonly=on,file=${OVMF_FIRMWARE}
|
||||
-m 512M
|
||||
-nographic
|
||||
-net none
|
||||
COMMENT "Testing QEMU UEFI boot (no OS image)"
|
||||
)
|
||||
else()
|
||||
message(WARNING "OVMF firmware not found. QEMU targets will not be available.")
|
||||
message(WARNING "Install OVMF:")
|
||||
message(WARNING " Ubuntu/Debian: sudo apt-get install ovmf")
|
||||
message(WARNING " Arch Linux: sudo pacman -S edk2-ovmf")
|
||||
message(WARNING " Fedora: sudo dnf install edk2-ovmf")
|
||||
endif()
|
||||
|
||||
# Print build configuration
|
||||
message(STATUS "MetalOS Build Configuration:")
|
||||
message(STATUS " Version: ${PROJECT_VERSION}")
|
||||
message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS " C Compiler: ${CMAKE_C_COMPILER}")
|
||||
message(STATUS " C++ Compiler: ${CMAKE_CXX_COMPILER}")
|
||||
message(STATUS " NASM: ${CMAKE_ASM_NASM_COMPILER}")
|
||||
message(STATUS " QEMU Display: ${QEMU_DISPLAY}")
|
||||
67
bootloader/CMakeLists.txt
Normal file
67
bootloader/CMakeLists.txt
Normal file
@@ -0,0 +1,67 @@
|
||||
# MetalOS Bootloader CMakeLists
|
||||
|
||||
# Bootloader-specific compiler flags
|
||||
set(BOOTLOADER_CFLAGS
|
||||
-fshort-wchar
|
||||
-fno-stack-check
|
||||
-DEFI_FUNCTION_WRAPPER
|
||||
)
|
||||
|
||||
# Bootloader-specific linker flags
|
||||
set(BOOTLOADER_LDFLAGS
|
||||
-shared
|
||||
-Bsymbolic
|
||||
-nostdlib
|
||||
-znocombreloc
|
||||
)
|
||||
|
||||
# Source files
|
||||
set(BOOTLOADER_SOURCES
|
||||
src/main.c
|
||||
)
|
||||
|
||||
# Include directories
|
||||
include_directories(include)
|
||||
|
||||
# Create bootloader object files
|
||||
add_library(bootloader_objs OBJECT
|
||||
${BOOTLOADER_SOURCES}
|
||||
)
|
||||
|
||||
target_compile_options(bootloader_objs PRIVATE ${BOOTLOADER_CFLAGS})
|
||||
|
||||
# Link bootloader as shared object first
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bootx64.so
|
||||
COMMAND ${CMAKE_LINKER}
|
||||
${BOOTLOADER_LDFLAGS}
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/uefi.lds
|
||||
$<TARGET_OBJECTS:bootloader_objs>
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/bootx64.so
|
||||
DEPENDS bootloader_objs ${CMAKE_CURRENT_SOURCE_DIR}/uefi.lds
|
||||
COMMENT "Linking bootloader shared object"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
# Convert to EFI binary
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi
|
||||
COMMAND ${CMAKE_OBJCOPY}
|
||||
-j .text -j .sdata -j .data -j .dynamic
|
||||
-j .dynsym -j .rel -j .rela -j .reloc
|
||||
--target=efi-app-x86_64
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bootx64.so
|
||||
${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bootx64.so
|
||||
COMMENT "Creating EFI bootloader binary"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
add_custom_target(bootloader ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi
|
||||
)
|
||||
|
||||
# Install bootloader binary
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/bootx64.efi
|
||||
DESTINATION bin
|
||||
)
|
||||
13
conan_profile
Normal file
13
conan_profile
Normal file
@@ -0,0 +1,13 @@
|
||||
[settings]
|
||||
os=Linux
|
||||
arch=x86_64
|
||||
compiler=gcc
|
||||
compiler.version=13
|
||||
compiler.libcxx=libstdc++11
|
||||
build_type=Release
|
||||
|
||||
[options]
|
||||
|
||||
[build_requires]
|
||||
|
||||
[env]
|
||||
62
conanfile.py
Normal file
62
conanfile.py
Normal file
@@ -0,0 +1,62 @@
|
||||
from conan import ConanFile
|
||||
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout
|
||||
|
||||
class MetalOSConan(ConanFile):
|
||||
name = "metalos"
|
||||
version = "0.1.0"
|
||||
|
||||
# Project metadata
|
||||
license = "MIT"
|
||||
author = "MetalOS Contributors"
|
||||
url = "https://github.com/johndoe6345789/MetalOS"
|
||||
description = "Minimal OS for QT6 on AMD64 + RX 6600"
|
||||
topics = ("os", "kernel", "uefi", "qt6", "minimal")
|
||||
|
||||
# Build settings
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
|
||||
# Build options
|
||||
options = {
|
||||
"with_tests": [True, False],
|
||||
"qemu_display": ["none", "gtk", "sdl"]
|
||||
}
|
||||
|
||||
default_options = {
|
||||
"with_tests": True,
|
||||
"qemu_display": "none"
|
||||
}
|
||||
|
||||
# Sources are in the same repo
|
||||
exports_sources = (
|
||||
"CMakeLists.txt",
|
||||
"bootloader/*",
|
||||
"kernel/*",
|
||||
"userspace/*",
|
||||
"tests/*",
|
||||
"scripts/*",
|
||||
"docs/*"
|
||||
)
|
||||
|
||||
def layout(self):
|
||||
cmake_layout(self)
|
||||
|
||||
def generate(self):
|
||||
tc = CMakeToolchain(self)
|
||||
tc.variables["BUILD_TESTING"] = self.options.with_tests
|
||||
tc.variables["QEMU_DISPLAY"] = str(self.options.qemu_display)
|
||||
tc.generate()
|
||||
|
||||
def build(self):
|
||||
cmake = CMake(self)
|
||||
cmake.configure()
|
||||
cmake.build()
|
||||
|
||||
if self.options.with_tests:
|
||||
cmake.test()
|
||||
|
||||
def package(self):
|
||||
cmake = CMake(self)
|
||||
cmake.install()
|
||||
|
||||
def package_info(self):
|
||||
self.cpp_info.libs = ["metalos"]
|
||||
307
docs/BUILD_SYSTEMS.md
Normal file
307
docs/BUILD_SYSTEMS.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# MetalOS Build Instructions
|
||||
|
||||
This document describes how to build MetalOS using various build systems.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Required Tools
|
||||
|
||||
- **Compiler**: GCC 11+ or Clang 13+
|
||||
- **Assembler**: NASM 2.14+
|
||||
- **CMake**: 3.16+
|
||||
- **Ninja** (optional): 1.10+
|
||||
- **Conan** (optional): 2.0+
|
||||
- **QEMU**: For testing (with OVMF firmware)
|
||||
|
||||
### Install on Ubuntu/Debian
|
||||
|
||||
```bash
|
||||
# Basic build tools
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential cmake nasm
|
||||
|
||||
# Ninja build system (optional but faster)
|
||||
sudo apt-get install -y ninja-build
|
||||
|
||||
# QEMU and UEFI firmware for testing
|
||||
sudo apt-get install -y qemu-system-x86 ovmf
|
||||
|
||||
# Conan package manager (optional)
|
||||
pip3 install conan
|
||||
```
|
||||
|
||||
### Install on Arch Linux
|
||||
|
||||
```bash
|
||||
sudo pacman -S base-devel cmake nasm ninja qemu edk2-ovmf
|
||||
pip install conan
|
||||
```
|
||||
|
||||
### Install on Fedora
|
||||
|
||||
```bash
|
||||
sudo dnf install gcc gcc-c++ cmake nasm ninja-build qemu edk2-ovmf
|
||||
pip install conan
|
||||
```
|
||||
|
||||
## Build Methods
|
||||
|
||||
### Method 1: CMake with Make (Traditional)
|
||||
|
||||
```bash
|
||||
# Configure
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
|
||||
# Build
|
||||
make -j$(nproc)
|
||||
|
||||
# Build specific targets
|
||||
make bootloader
|
||||
make kernel
|
||||
|
||||
# Test in QEMU
|
||||
make image
|
||||
make qemu
|
||||
```
|
||||
|
||||
### Method 2: CMake with Ninja (Faster)
|
||||
|
||||
```bash
|
||||
# Configure with Ninja
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja ..
|
||||
|
||||
# Build (much faster than make)
|
||||
ninja
|
||||
|
||||
# Build specific targets
|
||||
ninja bootloader
|
||||
ninja kernel
|
||||
|
||||
# Test in QEMU
|
||||
ninja image
|
||||
ninja qemu
|
||||
```
|
||||
|
||||
### Method 3: Conan + CMake (Modern)
|
||||
|
||||
```bash
|
||||
# Install dependencies (if any are added in future)
|
||||
conan install . --build=missing
|
||||
|
||||
# Build with Conan
|
||||
conan build .
|
||||
|
||||
# Or build with specific profile
|
||||
conan create . --build=missing
|
||||
```
|
||||
|
||||
### Method 4: Conan + Ninja (Recommended)
|
||||
|
||||
```bash
|
||||
# Configure Conan to use Ninja
|
||||
conan install . --build=missing -c tools.cmake.cmaketoolchain:generator=Ninja
|
||||
|
||||
# Build
|
||||
conan build .
|
||||
```
|
||||
|
||||
## Build Configuration
|
||||
|
||||
### CMake Options
|
||||
|
||||
```bash
|
||||
# Debug build
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
|
||||
# Release build (default)
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
|
||||
# Set QEMU display mode
|
||||
cmake -DQEMU_DISPLAY=gtk ..
|
||||
```
|
||||
|
||||
### Conan Options
|
||||
|
||||
```bash
|
||||
# With tests (default)
|
||||
conan build . -o with_tests=True
|
||||
|
||||
# Without tests
|
||||
conan build . -o with_tests=False
|
||||
|
||||
# Set QEMU display
|
||||
conan build . -o qemu_display=gtk
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Fastest Build (Recommended)
|
||||
|
||||
```bash
|
||||
# One-time setup
|
||||
pip3 install conan
|
||||
sudo apt-get install -y cmake ninja-build nasm
|
||||
|
||||
# Build and test
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja ..
|
||||
ninja
|
||||
ninja qemu
|
||||
```
|
||||
|
||||
### Simple Build (No extra tools)
|
||||
|
||||
```bash
|
||||
# Just CMake and Make
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
make -j$(nproc)
|
||||
make qemu
|
||||
```
|
||||
|
||||
## Build Targets
|
||||
|
||||
### Main Targets
|
||||
|
||||
- **all**: Build bootloader and kernel (default)
|
||||
- **bootloader**: Build UEFI bootloader only
|
||||
- **kernel**: Build kernel only
|
||||
- **image**: Create bootable disk image
|
||||
- **clean**: Clean build artifacts
|
||||
|
||||
### Testing Targets
|
||||
|
||||
- **test**: Run unit tests
|
||||
- **qemu**: Run in QEMU with UEFI
|
||||
- **qemu-debug**: Run with debug output
|
||||
- **qemu-gdb**: Run with GDB debugging
|
||||
- **qemu-uefi-test**: Test UEFI boot without OS
|
||||
|
||||
## Build Output
|
||||
|
||||
```
|
||||
build/
|
||||
├── bootloader/
|
||||
│ └── bootx64.efi # UEFI bootloader
|
||||
├── kernel/
|
||||
│ └── metalos.bin # Kernel binary
|
||||
└── metalos.img # Bootable disk image
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### NASM not found
|
||||
|
||||
```bash
|
||||
sudo apt-get install nasm
|
||||
# Or download from https://www.nasm.us/
|
||||
```
|
||||
|
||||
### OVMF firmware not found
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt-get install ovmf
|
||||
|
||||
# Arch Linux
|
||||
sudo pacman -S edk2-ovmf
|
||||
|
||||
# Fedora
|
||||
sudo dnf install edk2-ovmf
|
||||
```
|
||||
|
||||
### Ninja not found
|
||||
|
||||
```bash
|
||||
sudo apt-get install ninja-build
|
||||
# Or use make instead: cmake .. (without -G Ninja)
|
||||
```
|
||||
|
||||
### Conan not found
|
||||
|
||||
```bash
|
||||
pip3 install conan
|
||||
# Or use system package manager
|
||||
```
|
||||
|
||||
## Performance Tips
|
||||
|
||||
### Parallel Builds
|
||||
|
||||
```bash
|
||||
# Make (use all CPU cores)
|
||||
make -j$(nproc)
|
||||
|
||||
# Ninja (automatically uses all cores)
|
||||
ninja
|
||||
|
||||
# Conan
|
||||
conan build . -c tools.cmake.cmake_toolchain:jobs=$(nproc)
|
||||
```
|
||||
|
||||
### Incremental Builds
|
||||
|
||||
- Ninja is faster for incremental builds
|
||||
- Use `ccache` for faster recompilation:
|
||||
```bash
|
||||
sudo apt-get install ccache
|
||||
export CC="ccache gcc"
|
||||
export CXX="ccache g++"
|
||||
cmake ..
|
||||
```
|
||||
|
||||
### Clean Builds
|
||||
|
||||
```bash
|
||||
# Full clean
|
||||
rm -rf build/
|
||||
mkdir build && cd build
|
||||
cmake ..
|
||||
|
||||
# Or use target
|
||||
make clean # Make
|
||||
ninja clean # Ninja
|
||||
```
|
||||
|
||||
## Cross-Compilation
|
||||
|
||||
MetalOS is built for x86_64 bare metal. If you need a cross-compiler:
|
||||
|
||||
```bash
|
||||
# Install x86_64 bare metal toolchain
|
||||
sudo apt-get install gcc-x86-64-linux-gnu
|
||||
|
||||
# Configure CMake to use it
|
||||
cmake -DCMAKE_C_COMPILER=x86_64-linux-gnu-gcc ..
|
||||
```
|
||||
|
||||
## CI/CD Integration
|
||||
|
||||
### GitHub Actions Example
|
||||
|
||||
```yaml
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y cmake ninja-build nasm ovmf qemu-system-x86
|
||||
|
||||
- name: Build with Ninja
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja ..
|
||||
ninja
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd build
|
||||
ctest --output-on-failure
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [CMake Documentation](https://cmake.org/documentation/)
|
||||
- [Ninja Build System](https://ninja-build.org/)
|
||||
- [Conan Documentation](https://docs.conan.io/)
|
||||
- [NASM Documentation](https://www.nasm.us/doc/)
|
||||
79
kernel/CMakeLists.txt
Normal file
79
kernel/CMakeLists.txt
Normal file
@@ -0,0 +1,79 @@
|
||||
# MetalOS Kernel CMakeLists
|
||||
|
||||
# Include directories
|
||||
include_directories(include)
|
||||
|
||||
# Source files
|
||||
set(KERNEL_C_SOURCES
|
||||
src/main.c
|
||||
src/gdt.c
|
||||
src/interrupts.c
|
||||
)
|
||||
|
||||
set(KERNEL_ASM_SOURCES
|
||||
src/gdt_flush.asm
|
||||
src/interrupts_asm.asm
|
||||
)
|
||||
|
||||
# Kernel-specific C compiler flags
|
||||
set(KERNEL_CFLAGS
|
||||
-mcmodel=large
|
||||
-O2
|
||||
)
|
||||
|
||||
# Create kernel C object files
|
||||
add_library(kernel_c_objs OBJECT
|
||||
${KERNEL_C_SOURCES}
|
||||
)
|
||||
|
||||
target_compile_options(kernel_c_objs PRIVATE ${KERNEL_CFLAGS})
|
||||
target_include_directories(kernel_c_objs PRIVATE include)
|
||||
|
||||
# Create kernel ASM object files separately
|
||||
# We need to avoid CMake adding C flags to NASM
|
||||
foreach(asm_file ${KERNEL_ASM_SOURCES})
|
||||
get_filename_component(asm_name ${asm_file} NAME_WE)
|
||||
set(asm_obj ${CMAKE_CURRENT_BINARY_DIR}/${asm_name}.o)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${asm_obj}
|
||||
COMMAND ${CMAKE_ASM_NASM_COMPILER}
|
||||
-f elf64
|
||||
-I ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
-o ${asm_obj}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${asm_file}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${asm_file}
|
||||
COMMENT "Assembling ${asm_file}"
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
list(APPEND KERNEL_ASM_OBJS ${asm_obj})
|
||||
endforeach()
|
||||
|
||||
# Custom target for ASM objects
|
||||
add_custom_target(kernel_asm_objs
|
||||
DEPENDS ${KERNEL_ASM_OBJS}
|
||||
)
|
||||
|
||||
# Link kernel binary
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
COMMAND ${CMAKE_LINKER}
|
||||
-nostdlib
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld
|
||||
$<TARGET_OBJECTS:kernel_c_objs>
|
||||
${KERNEL_ASM_OBJS}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
DEPENDS kernel_c_objs kernel_asm_objs ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld
|
||||
COMMENT "Linking kernel binary"
|
||||
COMMAND_EXPAND_LISTS
|
||||
)
|
||||
|
||||
add_custom_target(kernel ALL
|
||||
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
)
|
||||
|
||||
# Install kernel binary
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/metalos.bin
|
||||
DESTINATION bin
|
||||
)
|
||||
25
kernel/include/kernel/gdt.h
Normal file
25
kernel/include/kernel/gdt.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef METALOS_KERNEL_GDT_H
|
||||
#define METALOS_KERNEL_GDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// GDT Entry structure
|
||||
typedef struct {
|
||||
uint16_t limit_low;
|
||||
uint16_t base_low;
|
||||
uint8_t base_middle;
|
||||
uint8_t access;
|
||||
uint8_t granularity;
|
||||
uint8_t base_high;
|
||||
} __attribute__((packed)) gdt_entry_t;
|
||||
|
||||
// GDT Pointer structure
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) gdt_ptr_t;
|
||||
|
||||
// Initialize the Global Descriptor Table
|
||||
void gdt_init(void);
|
||||
|
||||
#endif // METALOS_KERNEL_GDT_H
|
||||
37
kernel/include/kernel/interrupts.h
Normal file
37
kernel/include/kernel/interrupts.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef METALOS_KERNEL_INTERRUPTS_H
|
||||
#define METALOS_KERNEL_INTERRUPTS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// IDT Entry structure
|
||||
typedef struct {
|
||||
uint16_t offset_low; // Offset bits 0-15
|
||||
uint16_t selector; // Code segment selector
|
||||
uint8_t ist; // Interrupt Stack Table offset
|
||||
uint8_t type_attr; // Type and attributes
|
||||
uint16_t offset_mid; // Offset bits 16-31
|
||||
uint32_t offset_high; // Offset bits 32-63
|
||||
uint32_t zero; // Reserved
|
||||
} __attribute__((packed)) idt_entry_t;
|
||||
|
||||
// IDT Pointer structure
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} __attribute__((packed)) idt_ptr_t;
|
||||
|
||||
// CPU registers state (for interrupt handlers)
|
||||
typedef struct {
|
||||
uint64_t r15, r14, r13, r12, r11, r10, r9, r8;
|
||||
uint64_t rbp, rdi, rsi, rdx, rcx, rbx, rax;
|
||||
uint64_t int_no, err_code;
|
||||
uint64_t rip, cs, rflags, rsp, ss;
|
||||
} __attribute__((packed)) registers_t;
|
||||
|
||||
// Initialize Interrupt Descriptor Table
|
||||
void idt_init(void);
|
||||
|
||||
// Generic interrupt handler (called from assembly)
|
||||
void interrupt_handler(registers_t* regs);
|
||||
|
||||
#endif // METALOS_KERNEL_INTERRUPTS_H
|
||||
56
kernel/src/gdt.c
Normal file
56
kernel/src/gdt.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* MetalOS Kernel - Global Descriptor Table (GDT)
|
||||
*
|
||||
* Minimal GDT setup for x86_64 long mode
|
||||
* Only what's needed for our single-app OS
|
||||
*/
|
||||
|
||||
#include "kernel/gdt.h"
|
||||
|
||||
// GDT entries (minimal for x86_64)
|
||||
// In long mode, most segmentation is ignored, but we still need a valid GDT
|
||||
static gdt_entry_t gdt[5];
|
||||
static gdt_ptr_t gdt_ptr;
|
||||
|
||||
// Set a GDT entry
|
||||
static void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||
gdt[num].base_low = (base & 0xFFFF);
|
||||
gdt[num].base_middle = (base >> 16) & 0xFF;
|
||||
gdt[num].base_high = (base >> 24) & 0xFF;
|
||||
|
||||
gdt[num].limit_low = (limit & 0xFFFF);
|
||||
gdt[num].granularity = (limit >> 16) & 0x0F;
|
||||
gdt[num].granularity |= gran & 0xF0;
|
||||
gdt[num].access = access;
|
||||
}
|
||||
|
||||
// Load GDT (assembly)
|
||||
extern void gdt_flush(uint64_t);
|
||||
|
||||
// Initialize GDT
|
||||
void gdt_init(void) {
|
||||
gdt_ptr.limit = (sizeof(gdt_entry_t) * 5) - 1;
|
||||
gdt_ptr.base = (uint64_t)&gdt;
|
||||
|
||||
// Null descriptor
|
||||
gdt_set_gate(0, 0, 0, 0, 0);
|
||||
|
||||
// Kernel code segment (64-bit)
|
||||
// Access: Present, Ring 0, Code, Executable, Readable
|
||||
gdt_set_gate(1, 0, 0xFFFFFFFF, 0x9A, 0xA0);
|
||||
|
||||
// Kernel data segment (64-bit)
|
||||
// Access: Present, Ring 0, Data, Writable
|
||||
gdt_set_gate(2, 0, 0xFFFFFFFF, 0x92, 0xC0);
|
||||
|
||||
// User code segment (64-bit)
|
||||
// Access: Present, Ring 3, Code, Executable, Readable
|
||||
gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xA0);
|
||||
|
||||
// User data segment (64-bit)
|
||||
// Access: Present, Ring 3, Data, Writable
|
||||
gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xC0);
|
||||
|
||||
// Flush GDT
|
||||
gdt_flush((uint64_t)&gdt_ptr);
|
||||
}
|
||||
26
kernel/src/gdt_flush.asm
Normal file
26
kernel/src/gdt_flush.asm
Normal file
@@ -0,0 +1,26 @@
|
||||
; GDT flush assembly routine
|
||||
; Load new GDT and update segment registers
|
||||
|
||||
global gdt_flush
|
||||
extern gdt_ptr
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
|
||||
gdt_flush:
|
||||
lgdt [rdi] ; Load GDT pointer (first argument in rdi)
|
||||
|
||||
; Reload segments
|
||||
mov ax, 0x10 ; Kernel data segment offset
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
|
||||
; Far return to reload CS
|
||||
pop rdi ; Get return address
|
||||
mov rax, 0x08 ; Kernel code segment offset
|
||||
push rax
|
||||
push rdi
|
||||
retfq ; Far return
|
||||
160
kernel/src/interrupts.c
Normal file
160
kernel/src/interrupts.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* MetalOS Kernel - Interrupt Handling
|
||||
*
|
||||
* Minimal IDT and interrupt handlers
|
||||
* Only essential interrupts for QT6 app
|
||||
*/
|
||||
|
||||
#include "kernel/interrupts.h"
|
||||
|
||||
// IDT entries (256 interrupts in x86_64)
|
||||
static idt_entry_t idt[256];
|
||||
static idt_ptr_t idt_ptr;
|
||||
|
||||
// External ISR handlers (defined in interrupts_asm.asm)
|
||||
extern void isr0(void);
|
||||
extern void isr1(void);
|
||||
extern void isr2(void);
|
||||
extern void isr3(void);
|
||||
extern void isr4(void);
|
||||
extern void isr5(void);
|
||||
extern void isr6(void);
|
||||
extern void isr7(void);
|
||||
extern void isr8(void);
|
||||
extern void isr9(void);
|
||||
extern void isr10(void);
|
||||
extern void isr11(void);
|
||||
extern void isr12(void);
|
||||
extern void isr13(void);
|
||||
extern void isr14(void);
|
||||
extern void isr15(void);
|
||||
extern void isr16(void);
|
||||
extern void isr17(void);
|
||||
extern void isr18(void);
|
||||
extern void isr19(void);
|
||||
extern void isr20(void);
|
||||
extern void isr21(void);
|
||||
extern void isr22(void);
|
||||
extern void isr23(void);
|
||||
extern void isr24(void);
|
||||
extern void isr25(void);
|
||||
extern void isr26(void);
|
||||
extern void isr27(void);
|
||||
extern void isr28(void);
|
||||
extern void isr29(void);
|
||||
extern void isr30(void);
|
||||
extern void isr31(void);
|
||||
|
||||
// IRQ handlers
|
||||
extern void irq0(void);
|
||||
extern void irq1(void);
|
||||
|
||||
// Set an IDT entry
|
||||
static void idt_set_gate(uint8_t num, uint64_t handler, uint16_t selector, uint8_t flags) {
|
||||
idt[num].offset_low = handler & 0xFFFF;
|
||||
idt[num].offset_mid = (handler >> 16) & 0xFFFF;
|
||||
idt[num].offset_high = (handler >> 32) & 0xFFFFFFFF;
|
||||
idt[num].selector = selector;
|
||||
idt[num].ist = 0;
|
||||
idt[num].type_attr = flags;
|
||||
idt[num].zero = 0;
|
||||
}
|
||||
|
||||
// Remap PIC (Programmable Interrupt Controller)
|
||||
static void pic_remap(void) {
|
||||
// ICW1: Initialize PIC
|
||||
__asm__ volatile("outb %0, $0x20" : : "a"((uint8_t)0x11)); // Master PIC
|
||||
__asm__ volatile("outb %0, $0xA0" : : "a"((uint8_t)0x11)); // Slave PIC
|
||||
|
||||
// ICW2: Set interrupt vector offsets
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x20)); // Master offset to 0x20
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x28)); // Slave offset to 0x28
|
||||
|
||||
// ICW3: Set up cascade
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x04)); // Tell master about slave
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x02)); // Tell slave its cascade
|
||||
|
||||
// ICW4: Set mode
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0x01));
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0x01));
|
||||
|
||||
// Mask all interrupts initially
|
||||
__asm__ volatile("outb %0, $0x21" : : "a"((uint8_t)0xFF));
|
||||
__asm__ volatile("outb %0, $0xA1" : : "a"((uint8_t)0xFF));
|
||||
}
|
||||
|
||||
// Initialize IDT
|
||||
void idt_init(void) {
|
||||
idt_ptr.limit = (sizeof(idt_entry_t) * 256) - 1;
|
||||
idt_ptr.base = (uint64_t)&idt;
|
||||
|
||||
// Clear IDT
|
||||
for (int i = 0; i < 256; i++) {
|
||||
idt_set_gate(i, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Install exception handlers (ISRs 0-31)
|
||||
idt_set_gate(0, (uint64_t)isr0, 0x08, 0x8E);
|
||||
idt_set_gate(1, (uint64_t)isr1, 0x08, 0x8E);
|
||||
idt_set_gate(2, (uint64_t)isr2, 0x08, 0x8E);
|
||||
idt_set_gate(3, (uint64_t)isr3, 0x08, 0x8E);
|
||||
idt_set_gate(4, (uint64_t)isr4, 0x08, 0x8E);
|
||||
idt_set_gate(5, (uint64_t)isr5, 0x08, 0x8E);
|
||||
idt_set_gate(6, (uint64_t)isr6, 0x08, 0x8E);
|
||||
idt_set_gate(7, (uint64_t)isr7, 0x08, 0x8E);
|
||||
idt_set_gate(8, (uint64_t)isr8, 0x08, 0x8E);
|
||||
idt_set_gate(9, (uint64_t)isr9, 0x08, 0x8E);
|
||||
idt_set_gate(10, (uint64_t)isr10, 0x08, 0x8E);
|
||||
idt_set_gate(11, (uint64_t)isr11, 0x08, 0x8E);
|
||||
idt_set_gate(12, (uint64_t)isr12, 0x08, 0x8E);
|
||||
idt_set_gate(13, (uint64_t)isr13, 0x08, 0x8E);
|
||||
idt_set_gate(14, (uint64_t)isr14, 0x08, 0x8E);
|
||||
idt_set_gate(15, (uint64_t)isr15, 0x08, 0x8E);
|
||||
idt_set_gate(16, (uint64_t)isr16, 0x08, 0x8E);
|
||||
idt_set_gate(17, (uint64_t)isr17, 0x08, 0x8E);
|
||||
idt_set_gate(18, (uint64_t)isr18, 0x08, 0x8E);
|
||||
idt_set_gate(19, (uint64_t)isr19, 0x08, 0x8E);
|
||||
idt_set_gate(20, (uint64_t)isr20, 0x08, 0x8E);
|
||||
idt_set_gate(21, (uint64_t)isr21, 0x08, 0x8E);
|
||||
idt_set_gate(22, (uint64_t)isr22, 0x08, 0x8E);
|
||||
idt_set_gate(23, (uint64_t)isr23, 0x08, 0x8E);
|
||||
idt_set_gate(24, (uint64_t)isr24, 0x08, 0x8E);
|
||||
idt_set_gate(25, (uint64_t)isr25, 0x08, 0x8E);
|
||||
idt_set_gate(26, (uint64_t)isr26, 0x08, 0x8E);
|
||||
idt_set_gate(27, (uint64_t)isr27, 0x08, 0x8E);
|
||||
idt_set_gate(28, (uint64_t)isr28, 0x08, 0x8E);
|
||||
idt_set_gate(29, (uint64_t)isr29, 0x08, 0x8E);
|
||||
idt_set_gate(30, (uint64_t)isr30, 0x08, 0x8E);
|
||||
idt_set_gate(31, (uint64_t)isr31, 0x08, 0x8E);
|
||||
|
||||
// Remap PIC
|
||||
pic_remap();
|
||||
|
||||
// Install IRQ handlers (IRQs 0-15 mapped to 32-47)
|
||||
idt_set_gate(32, (uint64_t)irq0, 0x08, 0x8E); // Timer
|
||||
idt_set_gate(33, (uint64_t)irq1, 0x08, 0x8E); // Keyboard
|
||||
|
||||
// Load IDT
|
||||
__asm__ volatile("lidt %0" : : "m"(idt_ptr));
|
||||
|
||||
// Enable interrupts
|
||||
__asm__ volatile("sti");
|
||||
}
|
||||
|
||||
// Generic interrupt handler
|
||||
void interrupt_handler(registers_t* regs) {
|
||||
// Handle interrupt based on interrupt number
|
||||
(void)regs; // Suppress unused warning for now
|
||||
|
||||
// TODO: Dispatch to specific handlers based on regs->int_no
|
||||
|
||||
// Send EOI (End of Interrupt) to PIC if this was an IRQ
|
||||
if (regs->int_no >= 32 && regs->int_no < 48) {
|
||||
if (regs->int_no >= 40) {
|
||||
// Slave PIC
|
||||
__asm__ volatile("outb %0, $0xA0" : : "a"((uint8_t)0x20));
|
||||
}
|
||||
// Master PIC
|
||||
__asm__ volatile("outb %0, $0x20" : : "a"((uint8_t)0x20));
|
||||
}
|
||||
}
|
||||
120
kernel/src/interrupts_asm.asm
Normal file
120
kernel/src/interrupts_asm.asm
Normal file
@@ -0,0 +1,120 @@
|
||||
; Interrupt Service Routines (ISRs) for x86_64
|
||||
; Assembly stubs that save state and call C handler
|
||||
|
||||
global isr0, isr1, isr2, isr3, isr4, isr5, isr6, isr7
|
||||
global isr8, isr9, isr10, isr11, isr12, isr13, isr14, isr15
|
||||
global isr16, isr17, isr18, isr19, isr20, isr21, isr22, isr23
|
||||
global isr24, isr25, isr26, isr27, isr28, isr29, isr30, isr31
|
||||
global irq0, irq1
|
||||
|
||||
extern interrupt_handler
|
||||
|
||||
section .text
|
||||
bits 64
|
||||
|
||||
; Macro for ISRs without error code
|
||||
%macro ISR_NOERRCODE 1
|
||||
isr%1:
|
||||
push qword 0 ; Dummy error code
|
||||
push qword %1 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; Macro for ISRs with error code
|
||||
%macro ISR_ERRCODE 1
|
||||
isr%1:
|
||||
push qword %1 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; Macro for IRQs
|
||||
%macro IRQ 2
|
||||
irq%1:
|
||||
push qword 0 ; Dummy error code
|
||||
push qword %2 ; Interrupt number
|
||||
jmp isr_common_stub
|
||||
%endmacro
|
||||
|
||||
; CPU Exceptions (0-31)
|
||||
ISR_NOERRCODE 0 ; Divide by zero
|
||||
ISR_NOERRCODE 1 ; Debug
|
||||
ISR_NOERRCODE 2 ; Non-maskable interrupt
|
||||
ISR_NOERRCODE 3 ; Breakpoint
|
||||
ISR_NOERRCODE 4 ; Overflow
|
||||
ISR_NOERRCODE 5 ; Bound range exceeded
|
||||
ISR_NOERRCODE 6 ; Invalid opcode
|
||||
ISR_NOERRCODE 7 ; Device not available
|
||||
ISR_ERRCODE 8 ; Double fault
|
||||
ISR_NOERRCODE 9 ; Coprocessor segment overrun
|
||||
ISR_ERRCODE 10 ; Invalid TSS
|
||||
ISR_ERRCODE 11 ; Segment not present
|
||||
ISR_ERRCODE 12 ; Stack-segment fault
|
||||
ISR_ERRCODE 13 ; General protection fault
|
||||
ISR_ERRCODE 14 ; Page fault
|
||||
ISR_NOERRCODE 15 ; Reserved
|
||||
ISR_NOERRCODE 16 ; x87 floating-point exception
|
||||
ISR_ERRCODE 17 ; Alignment check
|
||||
ISR_NOERRCODE 18 ; Machine check
|
||||
ISR_NOERRCODE 19 ; SIMD floating-point exception
|
||||
ISR_NOERRCODE 20 ; Virtualization exception
|
||||
ISR_NOERRCODE 21 ; Reserved
|
||||
ISR_NOERRCODE 22 ; Reserved
|
||||
ISR_NOERRCODE 23 ; Reserved
|
||||
ISR_NOERRCODE 24 ; Reserved
|
||||
ISR_NOERRCODE 25 ; Reserved
|
||||
ISR_NOERRCODE 26 ; Reserved
|
||||
ISR_NOERRCODE 27 ; Reserved
|
||||
ISR_NOERRCODE 28 ; Reserved
|
||||
ISR_NOERRCODE 29 ; Reserved
|
||||
ISR_ERRCODE 30 ; Security exception
|
||||
ISR_NOERRCODE 31 ; Reserved
|
||||
|
||||
; IRQs (32-47)
|
||||
IRQ 0, 32 ; Timer
|
||||
IRQ 1, 33 ; Keyboard
|
||||
|
||||
; Common ISR stub - saves state and calls C handler
|
||||
isr_common_stub:
|
||||
; Save all general purpose registers
|
||||
push rax
|
||||
push rbx
|
||||
push rcx
|
||||
push rdx
|
||||
push rsi
|
||||
push rdi
|
||||
push rbp
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
push r12
|
||||
push r13
|
||||
push r14
|
||||
push r15
|
||||
|
||||
; Call C handler with pointer to register state
|
||||
mov rdi, rsp
|
||||
call interrupt_handler
|
||||
|
||||
; Restore all registers
|
||||
pop r15
|
||||
pop r14
|
||||
pop r13
|
||||
pop r12
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rbp
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rbx
|
||||
pop rax
|
||||
|
||||
; Clean up error code and interrupt number
|
||||
add rsp, 16
|
||||
|
||||
; Return from interrupt
|
||||
iretq
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
#include "kernel/kernel.h"
|
||||
#include "kernel/gdt.h"
|
||||
#include "kernel/interrupts.h"
|
||||
|
||||
/*
|
||||
* Kernel main entry point
|
||||
@@ -19,13 +21,13 @@ void kernel_main(BootInfo* boot_info) {
|
||||
// Suppress unused parameter warning
|
||||
(void)boot_info;
|
||||
|
||||
// TODO: Set up minimal page tables (identity mapped or simple offset)
|
||||
// Initialize GDT (Global Descriptor Table)
|
||||
gdt_init();
|
||||
|
||||
// TODO: Set up IDT with only interrupts we need:
|
||||
// - Keyboard/mouse (USB or PS/2)
|
||||
// - Timer (for QT event loop)
|
||||
// - GPU (if needed)
|
||||
// That's it! Maybe 5 interrupt handlers total.
|
||||
// Initialize IDT (Interrupt Descriptor Table)
|
||||
idt_init();
|
||||
|
||||
// TODO: Set up minimal page tables (identity mapped or simple offset)
|
||||
|
||||
// TODO: Simple memory allocator (bump allocator is fine)
|
||||
|
||||
|
||||
10
tests/CMakeLists.txt
Normal file
10
tests/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# MetalOS Tests CMakeLists
|
||||
|
||||
# Include test framework
|
||||
include_directories(include)
|
||||
|
||||
# Unit tests subdirectory
|
||||
add_subdirectory(unit)
|
||||
|
||||
# Integration tests can be added here later
|
||||
# add_subdirectory(integration)
|
||||
23
tests/unit/CMakeLists.txt
Normal file
23
tests/unit/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# MetalOS Unit Tests CMakeLists
|
||||
|
||||
# Test sources
|
||||
set(TEST_SOURCES
|
||||
test_bootloader.c
|
||||
)
|
||||
|
||||
# Create test executable for each test file
|
||||
foreach(test_src ${TEST_SOURCES})
|
||||
get_filename_component(test_name ${test_src} NAME_WE)
|
||||
|
||||
add_executable(${test_name} ${test_src})
|
||||
|
||||
# Link with test framework (if needed)
|
||||
target_include_directories(${test_name} PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/tests/include
|
||||
${CMAKE_SOURCE_DIR}/bootloader/include
|
||||
${CMAKE_SOURCE_DIR}/kernel/include
|
||||
)
|
||||
|
||||
# Add as test
|
||||
add_test(NAME ${test_name} COMMAND ${test_name})
|
||||
endforeach()
|
||||
10
userspace/CMakeLists.txt
Normal file
10
userspace/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
# MetalOS Userspace CMakeLists
|
||||
|
||||
# Placeholder for userspace components
|
||||
# Will be expanded when implementing user applications
|
||||
|
||||
message(STATUS "Userspace build configuration (placeholder)")
|
||||
|
||||
# Add subdirectories when ready
|
||||
# add_subdirectory(apps)
|
||||
# add_subdirectory(libs)
|
||||
Reference in New Issue
Block a user