mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-25 15:10:28 +00:00
Initial work on ZealBooter
This commit is contained in:
parent
12201e46b6
commit
69f0f37b9b
7 changed files with 224 additions and 9 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -3,4 +3,6 @@
|
|||
*.MAP
|
||||
src/Boot/
|
||||
docs/Boot/
|
||||
build/limine
|
||||
build/ovmf
|
||||
ZealOS-*.iso
|
||||
|
|
|
@ -35,6 +35,9 @@ umount_tempdisk() {
|
|||
|
||||
[ ! -d $TMPMOUNT ] && mkdir -p $TMPMOUNT
|
||||
|
||||
echo "Building ZealBooter..."
|
||||
( cd ../zealbooter && make clean all )
|
||||
|
||||
echo "Making temp vdisk, running auto-install..."
|
||||
qemu-img create -f raw $TMPDISK 192M
|
||||
qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -cdrom AUTO-VM-1.ISO -device isa-debug-exit
|
||||
|
@ -47,21 +50,25 @@ sudo cp -r ../src/* $TMPMOUNT
|
|||
[ ! -d "limine" ] && git clone https://github.com/limine-bootloader/limine.git --branch=v3.0-branch-binary --depth=1
|
||||
sudo mkdir -p $TMPMOUNT/EFI/BOOT
|
||||
sudo cp limine/BOOTX64.EFI $TMPMOUNT/EFI/BOOT/BOOTX64.EFI
|
||||
sudo cp ../zealbooter/zealbooter.elf $TMPMOUNT/Boot/ZealBooter.ELF
|
||||
umount_tempdisk
|
||||
|
||||
#echo "Generating ISO..."
|
||||
echo "Running temporary VM"
|
||||
echo "Rebuilding kernel..."
|
||||
qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -device isa-debug-exit
|
||||
qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -bios /usr/share/ovmf/OVMF.fd
|
||||
|
||||
#echo "Extracting ISO from vdisk..."
|
||||
#rm ./ZealOS-*.iso 2> /dev/null # comment this line if you want lingering old ISOs
|
||||
#mount_tempdisk
|
||||
#cp $TMPMOUNT/Tmp/MyDistro.ISO.C ./ZealOS-$(date +%Y-%m-%d-%H_%M_%S).iso
|
||||
#umount_tempdisk
|
||||
if [ ! -d "ovmf" ]; then
|
||||
echo "Downloading OVMF..."
|
||||
mkdir ovmf
|
||||
cd ovmf
|
||||
curl -o OVMF-X64.zip https://efi.akeo.ie/OVMF/OVMF-X64.zip
|
||||
7z x OVMF-X64.zip
|
||||
cd ..
|
||||
fi
|
||||
|
||||
echo "Testing..."
|
||||
qemu-system-x86_64 -machine q35,accel=kvm -drive format=raw,file=$TMPDISK -m 1G -rtc base=localtime -bios ovmf/OVMF.fd
|
||||
|
||||
echo "Deleting temp folder..."
|
||||
rm -rf $TMPDIR
|
||||
echo "Finished."
|
||||
#ls -lh ZealOS-*.iso
|
||||
|
||||
|
|
6
src/limine.cfg
Normal file
6
src/limine.cfg
Normal file
|
@ -0,0 +1,6 @@
|
|||
TIMEOUT=2
|
||||
|
||||
:ZealOS
|
||||
PROTOCOL=limine
|
||||
KERNEL_PATH=boot:///Boot/ZealBooter.ELF
|
||||
MODULE_PATH=boot:///Boot/Kernel.ZXE
|
6
zealbooter/.gitignore
vendored
Normal file
6
zealbooter/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
limine.h
|
||||
*.elf
|
||||
*.iso
|
||||
*.hdd
|
||||
*.o
|
||||
*.d
|
106
zealbooter/GNUmakefile
Normal file
106
zealbooter/GNUmakefile
Normal file
|
@ -0,0 +1,106 @@
|
|||
# This is the name that our final kernel executable will have.
|
||||
# Change as needed.
|
||||
override KERNEL := zealbooter.elf
|
||||
|
||||
# Convenience macro to reliably declare overridable command variables.
|
||||
define DEFAULT_VAR =
|
||||
ifeq ($(origin $1), default)
|
||||
override $(1) := $(2)
|
||||
endif
|
||||
ifeq ($(origin $1), undefined)
|
||||
override $(1) := $(2)
|
||||
endif
|
||||
endef
|
||||
|
||||
# It is highly recommended to use a custom built cross toolchain to build a kernel.
|
||||
# We are only using "cc" as a placeholder here. It may work by using
|
||||
# the host system's toolchain, but this is not guaranteed.
|
||||
$(eval $(call DEFAULT_VAR,CC,cc))
|
||||
|
||||
# Same thing for "ld" (the linker).
|
||||
$(eval $(call DEFAULT_VAR,LD,ld))
|
||||
|
||||
# User controllable CFLAGS.
|
||||
CFLAGS ?= -O2 -g -Wall -Wextra -Wpedantic -pipe
|
||||
|
||||
# User controllable preprocessor flags. We set none by default.
|
||||
CPPFLAGS ?=
|
||||
|
||||
# User controllable nasm flags.
|
||||
NASMFLAGS ?= -F dwarf -g
|
||||
|
||||
# User controllable linker flags. We set none by default.
|
||||
LDFLAGS ?=
|
||||
|
||||
# Internal C flags that should not be changed by the user.
|
||||
override CFLAGS += \
|
||||
-I. \
|
||||
-std=c11 \
|
||||
-ffreestanding \
|
||||
-fno-stack-protector \
|
||||
-fno-stack-check \
|
||||
-fno-pie \
|
||||
-fno-pic \
|
||||
-m64 \
|
||||
-march=x86-64 \
|
||||
-mabi=sysv \
|
||||
-mno-80387 \
|
||||
-mno-mmx \
|
||||
-mno-sse \
|
||||
-mno-sse2 \
|
||||
-mno-red-zone \
|
||||
-mcmodel=kernel \
|
||||
-MMD
|
||||
|
||||
# Internal linker flags that should not be changed by the user.
|
||||
override LDFLAGS += \
|
||||
-nostdlib \
|
||||
-static \
|
||||
-z max-page-size=0x1000 \
|
||||
-T linker.ld
|
||||
|
||||
# Internal nasm flags that should not be changed by the user.
|
||||
override NASMFLAGS += \
|
||||
-f elf64
|
||||
|
||||
# Use find to glob all *.c, *.S, and *.asm files in the directory and extract the object names.
|
||||
override CFILES := $(shell find ./ -type f -name '*.c')
|
||||
override ASFILES := $(shell find ./ -type f -name '*.S')
|
||||
override NASMFILES := $(shell find ./ -type f -name '*.asm')
|
||||
override OBJ := $(CFILES:.c=.o) $(ASFILES:.S=.o) $(NASMFILES:.asm=.o)
|
||||
override HEADER_DEPS := $(CFILES:.c=.d) $(ASFILES:.S=.d)
|
||||
|
||||
# Default target.
|
||||
.PHONY: all
|
||||
all: $(KERNEL)
|
||||
|
||||
limine.h:
|
||||
curl https://raw.githubusercontent.com/limine-bootloader/limine/trunk/limine.h -o $@
|
||||
|
||||
# Link rules for the final kernel executable.
|
||||
$(KERNEL): $(OBJ)
|
||||
$(LD) $(OBJ) $(LDFLAGS) -o $@
|
||||
|
||||
# Include header dependencies.
|
||||
-include $(HEADER_DEPS)
|
||||
|
||||
# Compilation rules for *.c files.
|
||||
%.o: %.c limine.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Compilation rules for *.S files.
|
||||
%.o: %.S limine.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
|
||||
|
||||
# Compilation rules for *.asm (nasm) files.
|
||||
%.o: %.asm
|
||||
nasm $(NASMFLAGS) $< -o $@
|
||||
|
||||
# Remove object files and the final executable.
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(KERNEL) $(OBJ) $(HEADER_DEPS)
|
||||
|
||||
.PHONY: distclean
|
||||
distclean: clean
|
||||
rm -f limine.h
|
53
zealbooter/linker.ld
Normal file
53
zealbooter/linker.ld
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* 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
|
||||
|
||||
.bss : {
|
||||
*(COMMON)
|
||||
*(.bss .bss.*)
|
||||
} :data
|
||||
|
||||
/* Discard .note.* and .eh_frame since they may cause issues on some hosts. */
|
||||
/DISCARD/ : {
|
||||
*(.eh_frame)
|
||||
*(.note .note.*)
|
||||
}
|
||||
}
|
35
zealbooter/zealbooter.c
Normal file
35
zealbooter/zealbooter.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
#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
|
||||
};
|
||||
|
||||
static void done(void) {
|
||||
for (;;) {
|
||||
__asm__("hlt");
|
||||
}
|
||||
}
|
||||
|
||||
// The following will be our kernel's entry point.
|
||||
void _start(void) {
|
||||
// Ensure we got a terminal
|
||||
if (terminal_request.response == NULL
|
||||
|| terminal_request.response->terminal_count < 1) {
|
||||
done();
|
||||
}
|
||||
|
||||
// We should now be able to call the Limine terminal to print out
|
||||
// a simple "Hello World" to screen.
|
||||
struct limine_terminal *terminal = terminal_request.response->terminals[0];
|
||||
terminal_request.response->write(terminal, "Hello World", 11);
|
||||
|
||||
// We're done, just hang...
|
||||
done();
|
||||
}
|
Loading…
Reference in a new issue