IPXEDIR=src
TARGETS=\
	bin/ipxe.lkrn\
	bin/ipxe.kpxe\
	bin/ipxe.usb\
	bin/undionly.kpxe\
	bin/virtio-net.rom\
	bin-x86_64-efi/ipxe.efi\
	bin-x86_64-efi/snponly.efi
ARM_TARGETS=\
	bin-arm32-efi/snp.efi
IPXE_CONFIGS="" com1 com2
IPXE_OPTS="NO_WERROR=1"
MEM=4G
CPU=-smp 2 -cpu Skylake-Client-noTSX-IBRS
OUT=gtk
MONITOR=stdio
NETMODEL=virtio
WNETMODEL=e1000
#NETOPTS=,ipv4
HOSTFWD=,hostfwd=tcp::2220-:22
IPV6=,ipv6=off
NET=-nic user,id=ens3,model=$(NETMODEL),mac=$(MAC)$(IPV6)$(HOSTFWD)$(NETOPTS)
USB=-usb -device usb-tablet
RNG=-object rng-random,id=rng0,filename=/dev/urandom -device virtio-rng-pci,rng=rng0,id=rng0
PARAMS:=
MAIN_SCRIPT=menu.ipxe
BOOTCONFIG=com1
BOOTFILE=ipxe/com1/undionly.kpxe
BOOTFILE_EFI=ipxe/ipxe.efi
BOOTORDER=c
OVMF=/usr/share/edk2/ovmf
EFI_BIOS=$(OVMF)/OVMF_CODE.fd
UNAME=$(shell uname -r)
MEMTEST_VERSION=$(shell	awk '/^set memtest_version / { print $$3 }' tools.ipxe)
C32S=hdt menu sysdump
IMGDIR=/opt/img/test
#DISKS=$(IMGDIR)/test.img
DISK1=/dev/vg_work/qemu_test1,format=raw
DISK2=/dev/vg_work/qemu_test2,format=raw
DISKS=$(DISK1)
DISKTMP=/tmp/test1.qcow2
DISKDRV=virtio
CACHE=none
#DISKS_FULL_PATH+=$(foreach disk,$(DISKS), $(IMGDIR)/$(disk))
override PARAMS+=$(foreach disk,$(DISKS),-drive file=$(disk),cache=$(CACHE),if=$(DISKDRV))
#override PARAMS+=-option-rom $(IPXEDIR)/bin/virtio-net.rom
CA_TRUST=/usr/share/pki/ca-trust-source/ca-bundle.trust.p11-kit

all:	rsync pciids.ipxe

.PHONY:	all clean sigs rsync compile syslinux

clean:
	+make -C sigs clean

sigs:
	+make -C sigs

rsync:	images/modules.cgz sigs
	rsync -avPHC --inplace --delete ./ www.salstar.sk:public_html/boot/ \
	  --exclude='**/.git*' --exclude='**/rsync' --exclude='src' \
	  --exclude='.well-known'
	# to tftp server for dhcp boot
	rsync -avPH --inplace --copy-unsafe-links \
		ipxe/*pxe ipxe/com* ipxe/*.efi ipxe/secureboot \
		ftp:/var/lib/tftpboot/ipxe/

TRUST=$(shell find `pwd`/certs/ -name \*.crt -o -name \*.pem | xargs echo $(CA_TRUST) | tr ' ' ',')
compile:	syslinux
	for config in $(IPXE_CONFIGS); do \
		make -j20 -C $(IPXEDIR) EMBEDDED_IMAGE=`pwd`/link.ipxe \
			TRUST=$(TRUST) $(TARGETS) $(IPXE_OPTS) \
			CONFIG=$$config; \
		#make -j20 -C $(IPXEDIR) EMBEDDED_IMAGE=`pwd`/link.ipxe \
		#	TRUST=$(TRUST) $(ARM_TARGETS) $(IPXE_OPTS) \
		#	CROSS_COMPILE=arm-linux-gnu- ARCH=arm32 \
		#	CONFIG=rpi; \
		for i in $(TARGETS); do \
			cp -av $(IPXEDIR)/$$i ipxe/$$config/; \
		done; \
		cp -av $(IPXEDIR)/bin-arm32-efi/snp.efi \
			ipxe/$$config/arm32.efi; \
		$(IPXEDIR)/util/genfsimg -o ipxe/$$config/ipxe.iso \
			$(IPXEDIR)/bin-x86_64-efi/ipxe.efi \
			$(IPXEDIR)/bin-arm32-efi/snp.efi \
			$(IPXEDIR)/bin/ipxe.lkrn; \
	done

ipxe_clean:
	+make -C $(IPXEDIR) clean distclean

updatesrc:
	cd src; git-update-show

recompile:	updatesrc
	@make compile
	@make

images/modules.cgz: images/pmagic/scripts/*
	cd images/pmagic; \
	find scripts modules | grep -v '/\.git' \
		| cpio --quiet -H newc -o | gzip -9 \
		> ../../$@

#$(IMGDIR)/$(DISKS):
#	qemu-img create $@ 8G

boot:	all
	qemu-kvm -m $(MEM) -machine q35 $(CPU) -boot once=$(BOOTORDER) \
		-kernel ipxe/$(BOOTCONFIG)/ipxe.lkrn \
		-monitor $(MONITOR) -display $(OUT) \
		$(NET) \
		$(USB) \
		$(RNG) \
		$(PARAMS) \
		$(ARGS)
	@echo ""

onlyboot:
	qemu-kvm -m $(MEM) -machine q35 $(CPU) -boot once=$(BOOTORDER) \
		-kernel ipxe/$(BOOTCONFIG)/ipxe.lkrn \
		-monitor $(MONITOR) -display $(OUT) \
		$(NET) \
		$(USB) \
		$(RNG) \
		$(PARAMS) \
		$(ARGS)
	@echo ""

textboot:
	# ncurses mode
	+make boot OUT=curses MONITOR=vc

stdioboot:
	# no-graphics, monitor on stdio
	@echo "Use CTRL+A + C + ENTER to QEMU monitor."
	+make boot OUT="none -nographic -serial mon:stdio" \
		 MONITOR=vc BOOTCONFIG=""
	reset # reset terminal

wboot:
	+make boot NET="$(NET) -net nic,id=vlan1,model=$(WNETMODEL)"

$(DISKTMP):
	qemu-img create -f qcow2 $@ 10g

ramboot:	$(DISKTMP)
	+make boot DISKS=$(DISKTMP),format=qcow2 CACHE=writeback

raidboot:
	+make boot DISKS="$(DISK1) $(DISK2)"

undiboot:	all
	qemu-kvm -m $(MEM) -machine q35 $(CPU) \
		 $(NET),tftp=`pwd`,bootfile=$(BOOTFILE) -boot n \
		-display $(OUT) $(USB) $(RNG) $(PARAMS) $(ARGS)

efiboot:	all
	qemu-kvm -m $(MEM) -machine q35 $(CPU) \
		$(NET),tftp=`pwd`,bootfile=$(BOOTFILE_EFI) \
		-boot n -bios $(EFI_BIOS) \
		-display $(OUT) $(USB) $(RNG) $(PARAMS) $(ARGS)

efiboot2:	all
	# efi boot with 2 disks for mirror
	+make efiboot DISKS="$(DISK1) $(DISK2)"

ramefiboot:	$(DISKTMP)
	+make efiboot DISKS=$(DISKTMP),format=qcow2 CACHE=writeback

secureboot:	all
	qemu-system-x86_64 -m $(MEM) -machine q35,smm=on $(CPU) \
		-global driver=cfi.pflash01,property=secure,value=on \
		-drive if=pflash,format=qcow2,unit=0,file=$(OVMF)/OVMF_CODE_4M.secboot.qcow2,readonly=on \
		-drive if=pflash,format=qcow2,unit=1,file=$(OVMF)/OVMF_VARS_4M.secboot.qcow2,snapshot=on \
		$(NET),tftp=`pwd`,bootfile=ipxe/secureboot/shimx64.efi \
		-boot n \
		-display $(OUT) $(USB) $(RNG) $(PARAMS) $(ARGS)

armboot:	all
	qemu-system-arm -M virt -m $(MEM) -device virtio-rng-pci \
		-pflash images/arm32_efi/flash0.img \
		-pflash images/arm32_efi/flash1.img \
		-drive file=fat:rw:ipxe/,format=raw,media=disk \
		-device virtio-net,netdev=n1 -netdev user,id=n1

# boot 2 virtual machines with 2 connected interfaces to test bonding
N2B1_NIC1=socket,id=ens8,listen=:6001
N2B1_NIC2=socket,id=ens9,listen=:6002
net2-boot1:
	make boot ARGS="-nic $(N2B1_NIC1) -nic $(N2B1_NIC2)"

N2B2_NIC1=socket,id=ens8,mac=00:00:00:01:01:01,connect=:6001
N2B2_NIC2=socket,id=ens9,mac=00:00:00:01:02:02,connect=:6002
N2B2_HOSTFWD=,hostfwd=tcp::2221-:22
net2-boot2:
	make ramboot ARGS="-nic $(N2B2_NIC1) -nic $(N2B2_NIC2)" \
		"HOSTFWD=$(N2B2_HOSTFWD)"

#pciids:	/usr/share/hwdata/pci.ids Makefile
#	awk ' \
#	  /^[0-9a-f]{4}/ { \
#	    vendor=substr($$1,1,4); \
#	    printf "#!ipxe\nset ven/%s\n", $$0 > "pciids/" vendor ".ipxe"; \
#	  } \
#	  /^\t[0-9a-f]{4}/ { \
#	    printf "set dev/%s%s\n", vendor, substr($$0, 2) > "pciids/" vendor ".ipxe" \
#	  } \
#	' $<

pciids.ipxe:	/usr/share/hwdata/pci.ids Makefile
	awk ' \
	  BEGIN { \
	    print "#!ipxe\ngoto $${vendor}$${device} || goto $${vendor} || exit" \
	  } \
	  /^[0-9a-f]{4}/ { \
	    vendor=substr($$1,1,4); \
	    printf ":%s\nset ven %s\nexit\n", vendor, substr($$0,7) \
	  } \
	  /^\t[0-9a-f]{4}/ { \
	    printf ":%s%s\nset dev %s\ngoto %s\n", \
	           vendor, substr($$0, 2, 4), substr($$0, 8), vendor \
	  } \
	' $< > $@

pxelinux.cfg/pci.ids:	/usr/share/hwdata/pci.ids
	cp -a $< $@

pxelinux.cfg/modules.pcimap:	/usr/lib/modules/$(UNAME)/modules.pcimap
	cp -a $< $@

pxelinux.cfg/modules.alias:	/usr/lib/modules/$(UNAME)/modules.alias
	cp -a $< $@

pxelinux.cfg/pxelinux.0:	/usr/share/syslinux/pxelinux.0
	cp -a $< $@

pxelinux.cfg/%.c32:	/usr/share/syslinux/%.c32
	cp -a $< $@

memdisk:	/usr/share/syslinux/memdisk
	cp -a $< $@

#images/memtest:	/boot/elf-memtest86+-$(MEMTEST_VERSION)
#	cp -a $< $@
#	touch $@

syslinux:	memdisk pxelinux.cfg/pci.ids pxelinux.cfg/modules.alias pxelinux.cfg/pxelinux.0 $(C32S:%=pxelinux.cfg/%.c32)
