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:
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=""