Switched to Makefile, use Limine for now

This commit is contained in:
Jozef Nagy 2024-11-25 17:48:07 +01:00
parent 251eb61d1b
commit 426fa865f0
Signed by: creoz
GPG key ID: 459A4811CEAC7068
29 changed files with 330 additions and 332 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

3
.gitignore vendored
View file

@ -2,6 +2,9 @@
# Build directories
build/
release/
ovmf/
sysroot/
# Emacs
\#*\#

4
.gitmodules vendored Normal file
View file

@ -0,0 +1,4 @@
[submodule "boot/limine"]
path = boot/limine
url = https://github.com/limine-bootloader/limine
branch = v8.x-binary

View file

@ -1,31 +0,0 @@
cmake_minimum_required(VERSION 3.30)
# Check if all important variables have been set
#
# Default values:
# - ARCH: amd64
# - PLATFORM: generic-pc
#
if (NOT DEFINED ARCH)
message(STATUS "Target architecture not set, choosing 'amd64' as default")
set(ARCH amd64)
endif()
if (NOT DEFINED PLATFORM)
message(STATUS "Target platform not set, choosing 'generic-pc' as default")
set(PLATFORM generic-pc)
endif()
# TODO: Check if arch/platform combo is valid
include(cmake/flags.cmake)
set(CMAKE_VERBOSE_MAKEFILE TRUE)
set(CMAKE_TOOLCHAIN_FILE "${CMAKE_SOURCE_DIR}/cmake/osdev.toolchain")
project(osdev)
enable_language(C ASM-ATT)
add_subdirectory(boot)

71
Makefile Normal file
View file

@ -0,0 +1,71 @@
MAKEFLAGS += -rR -s
##
# Build settings
#
ROOT_DIR := $(realpath $(shell dirname $(firstword $(MAKEFILE_LIST))))
include make/config.mk
##
# VM settings
#
include make/vm.mk
##
# Rules
#
.PHONY: all
all: kernel boot
.PHONY: boot
boot:
@$(MAKE) -C boot
.PHONY: kernel
kernel:
@$(MAKE) -C kernel
.PHONY: sysroot
sysroot: boot kernel
@mkdir -p $(SYSROOT_DIR)
@$(MAKE) -C boot install
@$(MAKE) -C kernel install
@cp -r base/* $(SYSROOT_DIR)
.PHONY: run
run: release-cd
@$(QEMU) $(QEMUFLAGS) -cdrom $(RELEASE_ISO)
.PHONY: run-uefi
run-uefi: ovmf release-cd
@$(QEMU) $(QEMUFLAGS) -cdrom $(RELEASE_ISO) -bios $(OVMF_DIR)/ovmf_$(ARCH).fd
.PHONY: release-full
release-full: release-cd release-hdd
.PHONY: release-cd
release-cd: $(RELEASE_ISO)
.PHONY: release-hdd
release-hdd: $(RELEASE_HDD)
$(RELEASE_ISO): sysroot
@mkdir -p $(RELEASE_DIR)
@./utils/generate-iso.sh $(SYSROOT_DIR) $@
$(RELEASE_HDD): sysroot
@mkdir -p $(RELEASE_DIR)
$(error HDD generation is not implemented yet.)
ovmf:
@./utils/download-ovmf.sh $(OVMF_DIR)
.PHONY: clean
clean:
@rm -rf $(SYSROOT_DIR) $(BUILD_DIR)
.PHONY: distclean
distclean: clean
@rm -rf $(OVMF_DIR) $(RELEASE_DIR)
@$(MAKE) -C boot/limine clean

View file

@ -0,0 +1,6 @@
timeout: 0
silent: yes
/OSDev
protocol: limine
kernel_path: boot():/System/krnl

BIN
boot/.DS_Store vendored Normal file

Binary file not shown.

View file

@ -1,14 +0,0 @@
project(boot)
enable_language(ASM C CXX)
add_subdirectory(platform/${PLATFORM})
# Do we support UEFI?
if((${ARCH} STREQUAL "amd64") OR
(${ARCH} STREQUAL "i686") OR
(${ARCH} STREQUAL "arm32") OR
(${ARCH} STREQUAL "arm64"))
add_subdirectory(platform/uefi)
endif()

10
boot/Makefile Normal file
View file

@ -0,0 +1,10 @@
.PHONY: all
all:
@$(MAKE) -C limine
.PHONY: install
install:
@mkdir -p $(SYSROOT_DIR)/boot/limine
@mkdir -p $(SYSROOT_DIR)/EFI/BOOT
@cp limine/limine-bios.sys limine/limine-bios-cd.bin limine/limine-uefi-cd.bin $(SYSROOT_DIR)/boot/limine
@cp limine/BOOTX64.EFI limine/BOOTIA32.EFI $(SYSROOT_DIR)/EFI/BOOT

1
boot/limine Submodule

@ -0,0 +1 @@
Subproject commit b9c91372b1f188902b97b4fca489fb0c16f1f871

View file

@ -1,44 +0,0 @@
# Check if we are compiling for a supported architecture
# and set appropriate architecture-specific
if(${ARCH} STREQUAL "amd64")
add_compile_flags("-m64")
add_link_flags("-m64")
set_compile_target(x86_64-unknown-none)
add_assembler_flags("--target=x86_64-unknown-none")
elseif(${ARCH} STREQUAL "i686")
add_compile_flags("-m32")
add_link_flags("-m32")
set_compile_target(i686-unknown-none)
add_assembler_flags("--target=i686-unknown-none")
else()
message(FATAL_ERROR "Unsupported architecture set for platform '${PLATFORM}'!")
endif()
project(boot)
add_compile_flags("-ffreestanding -fno-builtin -nostdinc")
## STAGE 2
set(STAGE2_SOURCES stage2/entry.asm)
add_executable(stage2 ${STAGE2_SOURCES})
target_include_directories(stage2 PRIVATE include include/arch/${ARCH} include/platform/generic-pc)
add_link_flags("-nostdlib -T${CMAKE_CURRENT_SOURCE_DIR}/stage2/linker.ld")
## STAGE 1
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-hdd.bin
COMMAND nasm -fbin -o "${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-hdd.bin" "${CMAKE_SOURCE_DIR}/boot/platform/generic-pc/stage1.asm" -DSTAGE1_HDD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/boot/platform/generic-pc")
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-cd.bin
COMMAND nasm -fbin -o "${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-cd.bin" "${CMAKE_SOURCE_DIR}/boot/platform/generic-pc/stage1.asm" -DSTAGE1_CD
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/boot/platform/generic-pc")
add_custom_target(stage1 ALL
DEPENDS stage2
${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-hdd.bin
${CMAKE_BINARY_DIR}/boot/platform/generic-pc/stage1-cd.bin)
## General
include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/arch/${ARCH})

View file

@ -1,59 +0,0 @@
[org 0x7c00]
[bits 16]
jmp _start
nop
%ifdef STAGE1_HDD
.bpb:
times 3 - ($ - $$) db 0 ; jmp short 3c;nop
.oem_identifier db "OSDEV "
.bytes_per_sector dw 512
.sectors_per_cluster db 0
.reserved_sectors dw 0
.fats db 0
.root_dirents dw 0
.total_sectors dw 0
.media_desc_type db 18
.sectors_per_fat dw 0
.sectors_per_track dw 0
.heads dw 0
.hidden_sectors dd 0
.large_sectors dd 0
.drive_number db 0
.flags db 0
.signature db 0
.volid dd 0
.vollabel db "OSDEV "
.sysident times 8 db 0
%elifdef STAGE1_CD
.eltorito:
.primary_vol_desc dd 0
.boot_file_loc dd 0
.boot_file_len dd 0
.checksum dd 1
.reserved times 40 db 0
%endif
;;;
_start:
;; set the video mode to an acceptable size
;; this also clears the screen
mov al, 0x03 ; 80x25
call set_video_mode
jmp halt
halt:
cli
hlt
jmp halt
%include "stage1/utils.inc"
times 510 - ($ - $$) db 0
dw 0xaa55
;;;; STAGE 2 ;;;;;
stage2:
;incbin STAGE2_BINARY

View file

@ -1,35 +0,0 @@
;; input: cx=string
print_error:
;; set a red background to catch the user's attention
mov ah, 0x0b
mov bh, 0x00
mov bl, 0x04
int 0x10
mov bx, cx
call print_str
_error_loop:
cli
hlt
jmp _error_loop
;; input: bx=string
print_str:
pusha
_print_char:
mov al, [bx]
cmp al, 0
je _print_end
mov ah, 0x0e
int 0x10
add bx, 1
jmp _print_char
_print_end:
popa
ret
;; input: al=mode
set_video_mode:
mov ah, 0x00
int 0x10
ret

View file

@ -1,6 +0,0 @@
.global stage2_entry
stage2_entry:
cli
hlt
jmp stage2_entry

View file

@ -1,25 +0,0 @@
OUTPUT_FORMAT("binary")
ENTRY(stage2_start)
SECTIONS
{
. = 0x8000;
.text : {
*(.text)
}
.data : {
*(.data)
}
.bss : {
*(.bss)
}
/DISCARD/ : {
*(.eh_frame)
}
ImageEndAddress = ALIGN(4);
}

View file

@ -1,55 +0,0 @@
# Check if we are compiling for a supported architecture
# and set appropriate architecture-specific
if(${ARCH} STREQUAL "amd64")
set(MACHINE_TYPE_SHORT_NAME "X64")
add_link_flags("/machine:X64")
add_compile_flags("-m64")
set_compile_target(x86_64-unknown-windows)
elseif(${ARCH} STREQUAL "i686")
set(MACHINE_TYPE_SHORT_NAME "IA32")
add_link_flags("/machine:X86")
add_compile_flags("-m32")
set_compile_target(i686-unknown-windows)
elseif(${ARCH} STREQUAL "arm32")
set(MACHINE_TYPE_SHORT_NAME "ARM")
add_link_flags("/machine:ARM")
add_compile_flags("-m32")
set_compile_target(arm-unknown-windows)
elseif(${ARCH} STREQUAL "arm64")
set(MACHINE_TYPE_SHORT_NAME "AA64")
add_link_flags("/machine:ARM64")
add_compile_flags("-m64")
set_compile_target(aarch64-unknown-windows)
else()
message(FATAL_ERROR "Unsupported architecture set for platform '${PLATFORM}'!")
endif()
set(UEFI_EXECUTABLE "BOOT${MACHINE_TYPE_SHORT_NAME}")
# Set some nice linker flags
add_link_flags("/LARGEADDRESSAWARE /MANIFEST:NO /NODEFAULTLIB /SAFESEH:NO")
# Entry point
add_link_flags("/ENTRY:efi_main")
# ...Yes, we *are* building an EFI application
add_link_flags("/SUBSYSTEM:EFI_APPLICATION,6.03")
add_link_flags("/VERSION:6.03")
# We have to tell CMake how to build our executable because it will shit itself otherwise
set(CMAKE_LINKER "lld-link")
set(CMAKE_C_LINK_EXECUTABLE "<CMAKE_LINKER> <LINK_FLAGS> <OBJECTS> /out:<TARGET> <LINK_LIBRARIES>")
project(boot)
# TODO: Find a better way to get sources
set(SOURCE_FILES "${CMAKE_SOURCE_DIR}/boot/platform/uefi/main.c")
add_executable(boot ${SOURCE_FILES})
set_target_properties(boot PROPERTIES OUTPUT_NAME ${UEFI_EXECUTABLE} SUFFIX .EFI)
include_directories(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/arch/${ARCH} ${CMAKE_SOURCE_DIR}/include/uefi)

View file

@ -1,5 +0,0 @@
int efi_main()
{
while (1);
return 0;
}

View file

@ -1,20 +0,0 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_ASM_COMPILER_WORKS TRUE)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang)
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_STATIC_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)

View file

@ -1,18 +0,0 @@
function(add_compile_flags flags)
set(CMAKE_C_COMPILER_FLAGS "${CMAKE_C_COMPILER_FLAGS} ${flags}" PARENT_SCOPE)
set(CMAKE_CXX_COMPILER_FLAGS "${CMAKE_CXX_COMPILER_FLAGS} ${flags}" PARENT_SCOPE)
set(CMAKE_ASM-ATT_FLAGS "${CMAKE_ASM-ATT_FLAGS} ${flags}" PARENT_SCOPE)
endfunction()
function(add_assembler_flags flags)
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${flags}" PARENT_SCOPE)
endfunction()
function(add_link_flags flags)
set(LINK_FLAGS "${LINK_FLAGS} ${flags}" PARENT_SCOPE)
endfunction()
function(set_compile_target target)
set(CMAKE_C_COMPILER_TARGET ${target} PARENT_SCOPE)
set(CMAKE_CXX_COMPILER_TARGET ${target} PARENT_SCOPE)
endfunction()

View file

@ -1,20 +0,0 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_CXX_COMPILER_WORKS TRUE)
set(CMAKE_ASM_COMPILER_WORKS TRUE)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang)
set(CMAKE_ASM-ATT_COMPILER clang)
set(CMAKE_C_STANDARD_LIBRARIES "" CACHE INTERNAL "")
set(CMAKE_EXE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_STATIC_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_MODULE_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_SHARED_LINKER_FLAGS "" CACHE INTERNAL "")
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)

62
kernel/Makefile Normal file
View file

@ -0,0 +1,62 @@
##
# Compilation options
#
KERN_CC := $(subst amd64,x86_64,$(ARCH))-elf-gcc
KERN_AS := $(subst amd64,x86_64,$(ARCH))-elf-gcc
KERN_LD := $(subst amd64,x86_64,$(ARCH))-elf-ld
KERN_CFLAGS := -Wall \
-Wextra \
-std=c99 \
-nostdinc \
-ffreestanding \
-fno-stack-protector \
-fno-stack-check \
-fno-lto \
-fno-pic \
-ffunction-sections \
-fdata-sections
KERN_ASFLAGS := -Wall \
-Wextra
KERN_LDFLAGS := -T arch/$(ARCH)/linker.ld
KERN_CPPFLAGS := -Iinclude \
-MMD \
-MP
include arch/$(ARCH)/flags.mk
##
# Source files
#
KERN_CFILES := $(shell find . -name '*.c' -not -path 'arch') $(shell find arch/$(ARCH) -name '*.c')
KERN_ASFILES := $(shell find arch/$(ARCH) -name '*.s')
KERN_OBJ := $(KERN_CFILES:%.c=$(BUILD_DIR)/%.c.o) $(KERN_ASFILES:%.S=$(BUILD_DIR)/%.S.o)
KERNEL_FILE := $(BUILD_DIR)/krnl
.PHONY: all
all: $(KERNEL_FILE)
$(KERNEL_FILE): $(KERN_OBJ)
@mkdir -p "$(@D)"
@printf " LD $(notdir $@)\n"
@$(KERN_LD) $(KERN_LDFLAGS) $(KERN_OBJ) -o $@
$(BUILD_DIR)/%.c.o: %.c
mkdir -p "$(@D)"
@printf " CC $<\n"
$(KERN_CC) $(KERN_CFLAGS) $(KERN_CPPFLAGS) -c $< -o $@
$(BUILD_DIR)/%.S.o: %.S
@mkdir -p "$(@D)"
@printf " CC $<\n"
@$(KERN_AS) $(KERN_ASFLAGS) $(KERN_CPPFLAGS) -c $< -o $@
.PHONY: install
install: $(KERNEL_FILE)
@mkdir -p $(SYSROOT_DIR)/System
@install -m 644 $(KERNEL_FILE) $(SYSROOT_DIR)/System/

View file

@ -0,0 +1,12 @@
KERNEL_CFLAGS += -m64 \
-march=x86-64 \
-mno-80387 \
-mno-mmx \
-mno-sse \
-mno-sse2 \
-mno-red-zone \
-mcmodel=kernel
KERNEL_ASFLAGS +=
KERNEL_LDFLAGS += -m elf_x86_64

View file

@ -0,0 +1,49 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start)
PHDRS
{
limine_requests PT_LOAD;
text PT_LOAD;
rodata PT_LOAD;
data PT_LOAD;
}
SECTIONS
{
. = 0xffffffff80000000;
.limine_requests : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
} :limine_requests
. = ALIGN(CONSTANT(MAXPAGESIZE));
.text : {
*(.text .text.*)
}
. = ALIGN(CONSTANT(MAXPAGESIZE));
.rodata : {
*(.rodata .rodata.*)
} :rodata
. = ALIGN(CONSTANT(MAXPAGESIZE));
.data : {
*(.data .data.*)
} :data
.bss : {
*(.bss .bss.*)
*(COMMON)
}
/DISCARD/ : {
*(.eh_frame*)
*(.note .note.*)
}
}

7
kernel/entryp.c Normal file
View file

@ -0,0 +1,7 @@
void _start()
{
// placeholder
for (;;) {
__asm__ volatile("cli;hlt");
}
}

36
make/config.mk Normal file
View file

@ -0,0 +1,36 @@
# Target architecture
ARCH ?= amd64
# OS Version
VERSION := 0.0.1
# Object files
BUILD_DIR ?= $(ROOT_DIR)/build
# OVMF Images
OVMF_DIR ?= $(ROOT_DIR)/ovmf
# System files
SYSROOT_DIR ?= $(ROOT_DIR)/sysroot
# Release files (.iso, .img, .vmdk, ...)
RELEASE_DIR ?= $(ROOT_DIR)/release
# Release images
RELEASE_IMAGE_NAME ?= osdev-v$(VERSION)_$(ARCH)
RELEASE_ISO := $(RELEASE_DIR)/$(RELEASE_IMAGE_NAME).iso
RELEASE_HDD := $(RELEASE_DIR)/$(RELEASE_IMAGE_NAME).img
##
# Export variables
#
export ARCH
export BUILD_DIR
export OVMF_DIR
export SYSROOT_DIR
export RELEASE_DIR
export RELEASE_ISO
export RELEASE_HDD

5
make/target.mk Normal file
View file

@ -0,0 +1,5 @@
aarch64_valid_targets := uefi rpi apl-scl
arm32_valid_targets := uefi rpi
amd64_valid_targets := generic-pc
i686_valid_targets := generic-pc

10
make/vm.mk Normal file
View file

@ -0,0 +1,10 @@
QEMU := qemu-system-$(subst amd64,x86_64,$(ARCH))
QEMUFLAGS ?= -m 256M
##
# Export variables
#
export QEMU
export QEMUFLAGS

27
utils/download-ovmf.sh Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
download() {
curl -s -o "${download_dir}/$2" -O "$1"
printf "[*] Downloaded $2\n"
}
download_dir=$1
# Check if we have provided a download directory
if [ -z "${download_dir}" ]; then
printf "[!] Download directory not supplied!\n"
printf "Usage: $0 <download_dir>\n"
exit 1
fi
# Check if curl is available
if [ ! -x "$(command -v curl)" ]; then
printf "[!] cURL was not found! Please install it or make sure the executable is in PATH.\n"
exit 1
fi
# Silently create the download directory if it doesn't exist yet
mkdir -p ${download_dir}
printf "[ ] Downloading OVMF images...\n"
download https://retrage.github.io/edk2-nightly/bin/RELEASEX64_OVMF.fd ovmf_amd64.fd

27
utils/generate-iso.sh Executable file
View file

@ -0,0 +1,27 @@
#!/usr/bin/env bash
sysroot_dir=$1
output_file=$2
# Check for empty input
if [ -z "${1}" ]; then
printf "[!] No arguments specified!\n"
printf "Usage: $0 <sysroot> <output>\n"
exit 1
fi
if [ -z "${2}" ]; then
printf "[!] No output filename specified!\n"
printf "Usage: $0 <sysroot> <output>\n"
exit 1
fi
# Check if xorriso is available
if [ ! -x "$(command -v xorriso)" ]; then
printf "[!] xorriso was not found! Please install it or make sure the executable is in PATH.\n"
exit 1
fi
xorriso -as mkisofs -R -r -J -b boot/limine/limine-bios-cd.bin -no-emul-boot -boot-load-size 4 -boot-info-table -hfsplus -apm-block-size 2048 --efi-boot boot/limine/limine-uefi-cd.bin -efi-boot-part --efi-boot-image --protective-msdos-label "${sysroot_dir}" -o "${output_file}" &>/dev/null
echo "[*] Generated $(basename ${output_file}).\n"