ekern

ekern.git
git clone git://git.lenczewski.org/ekern.git
Log | Files | Refs | README | LICENSE

commit 906535a2d8f653067fc7da103f870f2139a5edc7
parent 5ccc01e7a53e1ba2c68b8f02a72696d6bdedbd45
Author: MikoĊ‚aj Lenczewski <mblenczewski@gmail.com>
Date:   Sun, 14 Jul 2024 22:16:50 +0000

Simplify build system, focusing on amd64, arm64, and efistub

Diffstat:
Mbuild.sh | 127++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mclean.sh | 2--
Dconfig.sh | 14--------------
Deuser/asm-example/build.sh | 17-----------------
Deuser/c-example/build.sh | 5-----
Deuser/c-example/example.c | 0
Deuser/cpp-example/build.sh | 5-----
Minclude/efi.h | 2+-
Ascripts/qemu-aarch64.sh | 45+++++++++++++++++++++++++++++++++++++++++++++
Mscripts/qemu-amd64.sh | 44++++++++++++++++++++++++++++++++------------
Msrc/boot.c | 2++
Dsrc/boot.ld | 18------------------
Asrc/efistub.ld | 20++++++++++++++++++++
Dsrc/kernel-amd64.c | 4----
Msrc/kernel.c | 6++----
Dtoolchain.sh | 34----------------------------------
16 files changed, 176 insertions(+), 169 deletions(-)

diff --git a/build.sh b/build.sh @@ -1,78 +1,99 @@ #!/bin/sh -. "$(dirname $0)/toolchain.sh" - -BIN="$ROOT/bin" -OBJ="$ROOT/obj" -MNT="$ROOT/mnt/$ARCH" +#CONFIG_EFISTUB=1 + +TARGET="${1:-amd64}" + +AS="clang" +CC="clang" +LD="lld" + +OBJCOPY="llvm-objcopy" + +WARNINGS="-Wall -Wextra -Wpedantic -Werror" +CFLAGS="-std=c11 -ffreestanding -fno-stack-protector -fshort-wchar -mno-red-zone" +CPPFLAGS="-Iinclude" + +BOOT_LDFLAGS="-flavor link -subsystem:efi_application -entry:efi_main" +KERN_LDFLAGS="-flavor ld -e kmain" + +case $TARGET in + amd64) + UEFIARCH="X64" + BOOT_CFLAGS="-target x86_64-unknown-windows $CFLAGS $WARNINGS -Wno-microsoft-fixed-enum" + KERN_CFLAGS="-target x86_64-unknown-gnu $CFLAGS $WARNINGS -Wno-fixed-enum-extension" + ;; + aarch64) + UEFIARCH="AA64" + BOOT_CFLAGS="-target aarch64-unknown-windows $CFLAGS $WARNINGS -Wno-microsoft-fixed-enum" + KERN_CFLAGS="-target aarch64-unknown-gnu $CFLAGS $WARNINGS -Wno-fixed-enum-extension" + ;; + *) + echo "Unsupported target: $TARGET, must be one of: amd64 aarch64" + exit 1 + ;; +esac set -ex -mkdir -p $BIN $OBJ $MNT - -# build eboot (bin/eboot-$ARCH.efi) - -clang -o $OBJ/boot-$ARCH.o -c $ROOT/src/boot.c \ - --target=x86_64-unknown-windows -ffreestanding -mno-red-zone $CPPFLAGS - -clang -o $BIN/boot-$ARCH.efi $OBJ/boot-$ARCH.o \ - --target=x86_64-unknown-windows -nostdlib -Wl,-subsystem:efi_application -Wl,-entry:efi_main -fuse-ld=lld-link - -# build ekern (bin/ekern-$ARCH.sys) +mkdir -p bin obj mnt -$CC -o $OBJ/start.o -c $ROOT/src/kernel.c $CFLAGS $CPPFLAGS -$CC -o $OBJ/kernel-$ARCH.o -c $ROOT/src/kernel-$ARCH.c $CFLAGS $CPPFLAGS -$LD -o $BIN/kernel-$ARCH.elf -T $ROOT/src/kernel.ld $OBJ/start.o $OBJ/kernel-$ARCH.o -$OBJCOPY -O binary $BIN/kernel-$ARCH.elf $BIN/kernel-$ARCH.sys +if [ "${CONFIG_EFISTUB:-z}" = "z" ]; then -# build UEFI image (bin/uefi.sys) +# build kernel loader +$CC -o obj/boot.o -c src/boot.c $BOOT_CFLAGS $CPPFLAGS +$LD $BOOT_LDFLAGS -out:bin/boot.efi obj/boot.o -cat $BIN/boot-$ARCH.efi > $BIN/uefi.sys -# cat $BIN/boot-$ARCH.efi $BIN/kernel-$ARCH.sys > $BIN/uefi.sys +# build kernel +$CC -o obj/kernel.o -c src/kernel.c $KERN_CFLAGS $CPPFLAGS +$LD $KERN_LDFLAGS -T src/kernel.ld -o bin/kernel.elf obj/kernel.o -# build euser (mnt/$ARCH/* and bin/euser-$ARCH.img) +else -dd if=/dev/zero of=$BIN/euser-$ARCH.img bs=1048576 count=64 >/dev/null 2>&1 +# build kernel +$AS -o obj/efistub.o -c src/efistub-$TARGET.asm +$CC -o obj/kernel.o -c src/kernel.c $KERN_CFLAGS $CPPFLAGS +$LD -flavor ld -T src/efistub.ld -o bin/kernel.efi obj/efistub.o obj/kernel.o -for program in $USERLAND; do - ( - set +x - BIN="$(realpath "$BIN")"; - OBJ="$(realpath "$OBJ")"; - MNT="$(realpath "$MNT")"; - set -x - cd "$ROOT/euser/$program"; - . "./build.sh" - ) -done +fi -# create bootable disk image (bin/disk.img) +# build disk image (64 MiB ESP, 32 MiB data) # --- # see: https://wiki.osdev.org/Bootable_Disk -dd if=/dev/zero of=$BIN/disk.img bs=1M count=64 >/dev/null 2>&1 +dd if=/dev/zero of=mnt/disk.img bs=1M count=96 status=none -cat <<'EOF' | sfdisk $BIN/disk.img -label: gpt +cat <<EOF | sfdisk mnt/disk.img unit: sectors +label: gpt -type=U, start=2048, size=2048, bootable -type=L, start=4096 +type=U, start=2048, size=131072, bootable +type=L, start=$((2048+131072)) EOF -## format efi partition -dd if=/dev/zero of=$BIN/esp.img bs=512 count=2048 >/dev/null 2>&1 +## write ESP +dd if=/dev/zero of=mnt/esp.img bs=512 count=131072 status=none + +mformat -i mnt/esp.img -F :: +mmd -i mnt/esp.img ::/EFI ::/EFI/BOOT + +if [ "${CONFIG_EFISTUB:-z}" = "z" ]; then + mcopy -i mnt/esp.img bin/boot.efi ::/EFI/BOOT/BOOT$UEFIARCH.EFI + mcopy -i mnt/esp.img bin/kernel.elf ::/EFI/BOOT/kernel.elf +else + mcopy -i mnt/esp.img bin/kernel.efi ::/EFI/BOOT/BOOT$UEFIARCH.EFI +fi + +dd if=mnt/esp.img of=mnt/disk.img bs=512 count=131072 seek=2048 conv=notrunc status=none -mformat -i $BIN/esp.img -mmd -i $BIN/esp.img ::/EFI ::/EFI/BOOT -mcopy -i $BIN/esp.img $BIN/uefi.sys ::/EFI/BOOT/BOOT$UEFIARCH.EFI +## write data partition +dd if=/dev/zero of=mnt/dat.img bs=512 count=$((65535-2048-33)) status=none -dd if=$BIN/esp.img of=$BIN/disk.img bs=512 seek=2048 count=2048 conv=notrunc >/dev/null 2>&1 +mformat -i mnt/dat.img :: -## format data partition -## TODO: format remaining data partition instead of writing raw bytes -dd if=$BIN/euser-$ARCH.img of=$BIN/disk.img bs=512 seek=4096 conv=notrunc >/dev/null 2>&1 +## TODO: copy over any relevant data -# run qemu emulator +dd if=mnt/dat.img of=mnt/disk.img bs=512 seek=$((2048+141072)) conv=notrunc status=none -"$ROOT/scripts/qemu-$ARCH.sh" $ROOT/bin/disk.img +# run image under QEMU +scripts/qemu-$TARGET.sh $(realpath mnt/disk.img) diff --git a/clean.sh b/clean.sh @@ -1,7 +1,5 @@ #!/bin/sh -. "$(dirname $0)/config.sh" - set -ex rm -rf bin obj mnt diff --git a/config.sh b/config.sh @@ -1,14 +0,0 @@ -#!/bin/sh - -ROOT="$(dirname $0)" - -# target architecture, one of: amd64 aarch64 riscv64 -ARCH=amd64 - -# uefi architecture, corresponds to target arch: X64 -UEFIARCH=X64 - -# userland programs to compile, any under euser/ -#USERLAND="$USERLAND asm-example" -#USERLAND="$USERLAND c-example" -#USERLAND="$USERLAND cpp-example" diff --git a/euser/asm-example/build.sh b/euser/asm-example/build.sh @@ -1,17 +0,0 @@ -#!/bin/sh - -SOURCE="" -case $ARCH in - amd64|aarch64) - SOURCE="example-$ARCH.asm" - ;; - - *) - echo "Unsupported architecture: $ARCH" - exit 0 - ;; -esac - -set -ex - -$AS -o $MNT/asm-example.bin $SOURCE $ASMFLAGS diff --git a/euser/c-example/build.sh b/euser/c-example/build.sh @@ -1,5 +0,0 @@ -#!/bin/sh - -set -ex - -$CC -o $MNT/c-example.bin example.c $CFLAGS $CPPFLAGS $LDFLAGS diff --git a/euser/c-example/example.c b/euser/c-example/example.c diff --git a/euser/cpp-example/build.sh b/euser/cpp-example/build.sh @@ -1,5 +0,0 @@ -#!/bin/sh - -set -ex - -$CXX -o $MNT/cpp-example.bin example.cpp $CXXFLAGS $CPPFLAGS $LDFLAGS diff --git a/include/efi.h b/include/efi.h @@ -56,7 +56,7 @@ typedef umm efi_status_t; #define EFIERR(err) (EFI_ERROR | (err)) #define EFIWARN(err) (EFI_WARNING | (err)) -enum efi_status { +enum efi_status : u64 { EFI_SUCCESS = 0, EFI_WARN_UNKNOWN_GLYPH = EFIWARN(1), diff --git a/scripts/qemu-aarch64.sh b/scripts/qemu-aarch64.sh @@ -0,0 +1,45 @@ +#!/bin/sh + +# NOTE: replace this with the path to a downloaded OVMF image +FIRMWARE="/usr/share/qemu/edk2-aarch64-code.fd" + +EFI_CODE="$(dirname $1)/uefi-aarch64-code.fd" +EFI_VARS="$(dirname $1)/uefi-aarch64-vars.fd" + +set -e + +if [ ! -f $EFI_CODE ]; then + dd if=/dev/zero of=$EFI_CODE bs=1M count=64 status=none + dd if=$FIRMWARE of=$EFI_CODE conv=notrunc status=none +fi + +if [ ! -f $EFI_VARS ]; then + dd if=/dev/zero of=$EFI_VARS bs=1M count=64 status=none +fi + +qemu-system-aarch64 \ + -machine virt \ + -cpu max \ + -m 128M \ + -smp sockets=1,cpus=2 \ + -drive if=pflash,format=raw,unit=0,file=$EFI_CODE,readonly=on \ + -drive if=pflash,format=raw,unit=1,file=$EFI_VARS \ + -drive if=none,format=raw,id=disk0,file="$1" \ + -device nvme,serial=12345678,drive=disk0 \ + -net none \ + -nographic + + #-chardev stdio,id=char0,logfile="serial.log",signal=off \ + #-serial chardev:char0 \ + +## alternative disk controllers: + +## ahci +# -device ahci,id=ahci \ +# -device ide-hd,drive=disk0,bus=ahci.0 \ + +## ide +# -device ide-hd,drive=disk0,bus=ide.0 \ + +## virtio +# -device virtio-blk,drive=disk0 \ diff --git a/scripts/qemu-amd64.sh b/scripts/qemu-amd64.sh @@ -1,24 +1,44 @@ #!/bin/sh # NOTE: replace this with the path to a downloaded OVMF image -OVMF_CODE="/usr/share/edk2-ovmf/OVMF_CODE.fd" -OVMF_VARS="/usr/share/edk2-ovmf/OVMF_VARS.fd" +FIRMWARE="/usr/share/qemu/edk2-x86_64-code.fd" -# params: -# $1 - disk image +EFI_CODE="$(dirname $1)/uefi-amd64-code.fd" +EFI_VARS="$(dirname $1)/uefi-amd64-vars.fd" + +set -e + +if [ ! -f $EFI_CODE ]; then + dd if=$FIRMWARE of=$EFI_CODE conv=notrunc status=none +fi + +if [ ! -f $EFI_VARS ]; then + dd if=/dev/zero of=$EFI_VARS bs=1M count=4 status=none +fi qemu-system-x86_64 \ - -drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \ - -drive if=pflash,format=raw,unit=1,file=$OVMF_VARS,readonly=on \ + -machine q35 \ + -cpu max \ + -m 128M \ + -smp sockets=1,cpus=2 \ + -drive if=pflash,format=raw,unit=0,file=$EFI_CODE,readonly=on \ + -drive if=pflash,format=raw,unit=1,file=$EFI_VARS \ -drive if=none,format=raw,id=disk0,file="$1" \ - -device ahci,id=ahci \ - -device ide-hd,drive=disk0,bus=ahci.0 \ + -device nvme,serial=12345678,drive=disk0 \ -net none \ -nographic - #-machine q35 \ - #-m 64 \ - #-smp sockets=1,cpus=4 \ - #-chardev stdio,id=char0,logfile="serial.log",signal=off \ #-serial chardev:char0 \ + +## alternative disk controllers: + +## ahci +# -device ahci,id=ahci \ +# -device ide-hd,drive=disk0,bus=ahci.0 \ + +## ide +# -device ide-hd,drive=disk0,bus=ide.0 \ + +## virtio +# -device virtio-blk,drive=disk0 \ diff --git a/src/boot.c b/src/boot.c @@ -2,6 +2,8 @@ EFI_IMAGE_ENTRY_POINT(efi_main) { + (void) image_handle; + efi_status_t status; #if 1 diff --git a/src/boot.ld b/src/boot.ld @@ -1,18 +0,0 @@ -ENTRY(EntryPoint) - -SECTIONS -{ - . = 0x40000; - - .header : { - *(.header) - } - - .text : { - *(.text) - } - - .data : { - *(.data) - } -} diff --git a/src/efistub.ld b/src/efistub.ld @@ -0,0 +1,20 @@ +SECTIONS +{ + . = 0x100000; + + .text : { + *(.text) + } + + .data : { + *(.data) + } + + .rodata : { + *(.rodata) + } + + .bss : { + *(.bss) + } +} diff --git a/src/kernel-amd64.c b/src/kernel-amd64.c @@ -1,4 +0,0 @@ -void -kmain(void) -{ -} diff --git a/src/kernel.c b/src/kernel.c @@ -1,7 +1,5 @@ -extern void kmain(void); - void -_start(void) +kmain(void) { - kmain(); + for (;;); } diff --git a/toolchain.sh b/toolchain.sh @@ -1,34 +0,0 @@ -#!/bin/sh - -. "$(dirname $0)/config.sh" - -TARGET="" -case $ARCH in - amd64) - TARGET="x86_64-unknown-elf" - ;; - - aarch64) - TARGET="aarch64-unknown-elf" - ;; - - riscv64) - TARGET="riscv64-unknown-elf" - ;; - - *) - echo "Unsupported architecture: $ARCH. Please see config.sh for all supported architectures" - exit 1 - ;; -esac - -export CC="clang" -export CXX="clang++" -export LD="ld.lld" -export OBJCOPY="llvm-objcopy" - -export ASFLAGS="--target=$TARGET" -export CFLAGS="--target=$TARGET -ffreestanding -nostdlib -nostdinc" -export CXXFLAGS="--target=$TARGET -ffreestanding -nostdlib -nostdinc" -export CPPFLAGS="-DEARCH=$ARCH -Iinclude" -export LDFLAGS=""