# SPDX-License-Identifier: Apache-2.0 # Any linux host toolchain should work as a default CC ?= gcc OBJCOPY ?= objcopy QEMU ?= qemu-system-x86_64 # No unwind tables is just to save size. No SSE is allowed because GCC # uses it for miscellaneous optimizations that aren't related to # floating point, and we don't want to take the traps except on # threads that definitely need it. No red zone because it's # incompatible with traditional stack-based interrupt entry. CFLAGS = -Os -I../include -std=c11 -ffreestanding -fno-pic -fno-asynchronous-unwind-tables -mno-sse -mno-red-zone LDFLAGS = -Wl,--build-id=none -nostdlib -nodefaultlibs -nostartfiles # This works great. But note that distros ship no libgcc for the # target, so once we start to need stuff from that we'll need to move # to a custom cross compiler. ARCHFLAGS = -mx32 # The default build target just links the stub files. Broader OS # builds just care about these files. The xuk.elf target is a # demonstration kernel. stubs: xuk-stub32.bin xuk-stub16.bin # First link the initial 32 bit stub, which goes at the front of our # image. xuk-stub32.bin: xuk-stub32.c *.h xuk-stub32.ld $(CC) -Wall -m32 $(CFLAGS) -c xuk-stub32.c $(CC) -m32 -T xuk-stub32.ld $(LDFLAGS) -no-pie -o stub32.elf $(CFLAGS) xuk-stub32.o $(OBJCOPY) -O binary stub32.elf $@ # This is the main OS image, starting with the 32 bit stub and # containing all the 64 bit code. xuk.elf64: xuk-stub32.bin xuk-stub16.bin xuk.c xuk-stubs.c demo-kernel.c *.h xuk64.ld $(CC) $(ARCHFLAGS) -Wall $(CFLAGS) -c xuk.c $(CC) $(ARCHFLAGS) -Wall $(CFLAGS) -c xuk-stubs.c $(CC) $(ARCHFLAGS) -Wall $(CFLAGS) -c demo-kernel.c $(CC) $(ARCHFLAGS) -T xuk64.ld $(LDFLAGS) -o $@ $(CFLAGS) xuk.o xuk-stubs.o demo-kernel.o # Final step. We now have an x86_64 ELF binary, which is not a valid # multiboot image as the entry point is of course 32 bit. It needs to # be a i386 image, so copy out the segment and relink the blob one # last time. xuk.elf: xuk.elf64 xuk64.ld $(OBJCOPY) -O binary $< xuk.bin echo '.incbin "xuk.bin"' | as --32 -c - -o xuk32.o $(CC) -m32 -T xuk64.ld $(LDFLAGS) -o $@ $(CFLAGS) xuk32.o # We can rely on the bootloader to handover a machine running in 386 # protected mode, but SMP cores start in real mode and need a tiny # bootstrap layer of 16 bit code. xuk-stub16.bin: xuk-stub16.c $(CC) -m16 $(CFLAGS) -c $< $(OBJCOPY) -O binary -j .text xuk-stub16.o $@ run: xuk.elf $(QEMU) -serial mon:stdio -smp cpus=2 -icount shift=1 -no-reboot -no-shutdown -d unimp,pcall,guest_errors -kernel $< clean: rm -f *.elf *.elf64 *.o *~ *.bin *.disasm