BUILD=./build # Default rule .PHONY: default default: all # Remove all build files .PHONY: clean clean: rm -drf $(BUILD) cd tetros; cargo clean # Make everything # (but don't run qemu) .PHONY: all all: img # # MARK: boot # # Compile tetros as library LIB_SRC = ./tetros/Cargo.toml ./tetros/Cargo.lock $(shell find ./tetros/src -type f) $(BUILD)/tetros.lib: $(LIB_SRC) @mkdir -p $(BUILD) cd tetros && \ env RUSTFLAGS="-C soft-float" \ cargo rustc \ --manifest-path="./Cargo.toml" \ -Z build-std=core \ -Z build-std-features=compiler-builtins-mem \ --target "./targets/x86-unknown-none.json" \ --lib \ --release \ -- \ --emit link="$(CURDIR)/$@" # Link tetros BIOS_LD = ./tetros/linkers/x86-unknown-none.ld $(BUILD)/tetros.elf: $(BUILD)/tetros.lib $(BIOS_LD) ld \ -m elf_i386 \ --gc-sections \ -z max-page-size=0x1000 \ -T "$(BIOS_LD)" \ -o "$@" \ "$<" objcopy --only-keep-debug "$@" "$@.sym" objcopy --strip-debug "$@" # Wrap tetros in three-stage BIOS loader # Parameters: # - BIOS_SRC: source directory of bios assembly # - STAGE2_SECTOR: the index of the first sector of the stage 2 binary on the disk BIOS_SRC = ./bios STAGE2_SECTOR = 1 $(BUILD)/bios.bin: $(wildcard $(BIOS_SRC)/*.asm) $(BUILD)/tetros.elf @mkdir -p "$(BUILD)" nasm \ -f bin \ -D STAGE3=$(BUILD)/tetros.elf \ -D STAGE2_SECTOR=$(STAGE2_SECTOR) \ -o "$@" \ -l "$@.lst" \ -i "$(BIOS_SRC)" \ "$(BIOS_SRC)/main.asm" # Extract full mbr (first 512 bytes) $(BUILD)/mbr.bin: $(BUILD)/bios.bin @mkdir -p "$(BUILD)" @echo "" dd if="$<" bs=512 count=1 of="$@" # Extract stage 2 (rest of file) $(BUILD)/stage2.bin: $(BUILD)/bios.bin @mkdir -p "$(BUILD)" @echo "" dd if="$<" bs=512 skip=1 of="$@" # # MARK: bundle # # Make full disk image .PHONY: img img: $(BUILD)/disk.img $(BUILD)/disk.img: $(BUILD)/mbr.bin $(BUILD)/stage2.bin @mkdir -p $(BUILD) @echo "" dd if="$(BUILD)/mbr.bin" of=$@ conv=notrunc bs=512 dd if="$(BUILD)/stage2.bin" of=$@ conv=notrunc seek=$(STAGE2_SECTOR) bs=512 .PHONY: qemu qemu: $(BUILD)/disk.img qemu-system-i386 \ -d cpu_reset \ -no-reboot \ -smp 1 -m 2048 \ -machine q35 \ -net none \ -serial stdio \ -fda "$<" # Same as qemu, but with no dependency. # Used for remote dev, where build box != run box. .PHONY: qemu-remote qemu-remote: qemu-system-i386 \ -d cpu_reset \ -no-reboot \ -smp 1 -m 2048 \ -machine q35 \ -net none \ -serial stdio \ -fda "$(BUILD)/disk.img" # Same as qemu, but with gdb options .PHONY: qemu-gdb qemu-gdb: $(BUILD)/disk.img qemu-system-i386 \ -d cpu_reset \ -no-reboot \ -smp 1 -m 2048 \ -machine q35 \ -net none \ -serial stdio \ -fda "$<" \ -gdb tcp::26000 \ -S # Do not use `-enable-kvm` or `-cpu host`, # this confuses gdb.