PROJECT_ROOT := $(abspath ..)
override TOOLCHAIN_DIR := $(PROJECT_ROOT)/toolchain
override CROSS := $(TOOLCHAIN_DIR)/cross/bin/ia16-elf-
BUILD ?= ../build/userland
PYTHON ?= python3
SERVER_SRC_ROOT := ../kern/system/service
KERNEL_MAX_PORTS ?= 32
KERNEL_MAX_TASKS ?= 40
KERNEL_MAX_USER_PROCS ?= 14
KERNEL_MAX_SOCK_ADDR ?= 110
KERNEL_UNIX_PATH_MAX ?= 20
KERNEL_NATIVE_MOUNT_MAX ?= 8
KERNEL_NATIVE_MAX_NODES ?= 40
FSYS_MAX_FDS ?= 32
FSYS_MAX_NODES ?= $(KERNEL_NATIVE_MAX_NODES)
FSYS_MAX_MOUNTS ?= 8
FSYS_PTYS ?= 4
FSYS_PTY_BUF_BYTES ?= 128
KLOG_BUFFER_BYTES ?= 512
KERNEL_UTS_SYSNAME ?= Antler
KERNEL_UTS_NODENAME ?= antler86
KERNEL_UTS_RELEASE ?= 0.1
KERNEL_UTS_VERSION ?= Antler/86-0.1-GEM-POSIX-core
KERNEL_UTS_MACHINE ?= i8086
ROOT_BLOCK_BACKEND ?= xtide
XTIDE_IO ?= 0x0300
ANTLER_LPT_BASE ?= 0x0378u
GEM_VIDEO_ADAPTER ?= pega
ROOT_DEVICE ?= $(if $(filter mfm,$(ROOT_BLOCK_BACKEND)),/dev/mfm0p1,/dev/hda1)
ROOT_FS_TYPE ?= ext2
ROOT_FLAGS ?= rw
ifneq ($(ROOT_FS_TYPE),ext2)
$(error ROOT_FS_TYPE=$(ROOT_FS_TYPE) is unsupported; Antler supports ext2 only)
endif
BOOT_GEOM_SECT ?= 17
BOOT_GEOM_HEAD ?= 4
BOOT_GEOM_CYL ?= 612

# A direct userland build does not necessarily pass through the repository
# Makefile.  Repeat the XTIDE profile gate here so a classroom experiment
# cannot compile a wrapped BASE + register port into driverd.  The normalized
# first field is valid input for both GNU C and preprocessed GNU assembly.
XTIDE_PROFILE_VALIDATOR := $(PROJECT_ROOT)/scripts/validate-xtide-geometry.py
USERLAND_XTIDE_IO_PROFILE := $(shell python3 $(XTIDE_PROFILE_VALIDATOR) io '$(XTIDE_IO)' 2>/dev/null || printf '%s\n' invalid)
ifeq ($(firstword $(USERLAND_XTIDE_IO_PROFILE)),invalid)
$(error XTIDE_IO=$(XTIDE_IO) must be one unsigned C-style integer literal from 1 through 0xfff0; zero is uninitialized and the 16-port XTIDE window must not wrap)
endif
USERLAND_XTIDE_IO_LITERAL := $(word 1,$(USERLAND_XTIDE_IO_PROFILE))

# Userland may be built directly during classroom exercises, without entering
# through the top-level Makefile.  Repeat the same host-side geometry gate here
# so that no direct build can form a target C literal wider than one unsigned
# 8086 word.  The fourth helper field is the validated exclusive sector count.
XTIDE_GEOMETRY_VALIDATOR := $(PROJECT_ROOT)/scripts/validate-xtide-geometry.py
USERLAND_HD_GEOMETRY := $(shell python3 $(XTIDE_GEOMETRY_VALIDATOR) chs '$(BOOT_GEOM_SECT)' '$(BOOT_GEOM_HEAD)' '$(BOOT_GEOM_CYL)' 2>/dev/null || printf '%s\n' invalid)
ifeq ($(firstword $(USERLAND_HD_GEOMETRY)),invalid)
$(error BOOT_GEOM_SECT, BOOT_GEOM_HEAD, and BOOT_GEOM_CYL must be positive decimal integers whose product is at most 65535)
endif
USERLAND_HD_IMAGE_SECTORS := $(word 4,$(USERLAND_HD_GEOMETRY))

ifeq ($(ROOT_BLOCK_BACKEND),ide)
override ROOT_BLOCK_BACKEND := xtide
endif
ifeq ($(ROOT_BLOCK_BACKEND),mfm)
ifeq ($(ROOT_DEVICE),/dev/hda1)
override ROOT_DEVICE := /dev/mfm0p1
endif
endif
BOOT_OPTIONS ?=
SYSINIT_EXTRA_LINE ?=
GEM_RUNLEVEL ?= 3

# Keep local recovery graphical.  These are the only supported init levels:
# normal GEM Login at level 3 and standalone GEM Terminal at level 1.  A
# separate COM1 getty is available at both levels; it is an authenticated
# serial administration path, not a physical-screen text console.
ifeq ($(filter $(GEM_RUNLEVEL),1 3),)
$(error unsupported GEM_RUNLEVEL=$(GEM_RUNLEVEL); use 3 for GEM Login or 1 for GEM Terminal)
endif
ifneq ($(words $(GEM_RUNLEVEL)),1)
$(error GEM_RUNLEVEL must be exactly one level: 1 or 3)
endif
KERNEL_DEBUG_TTY ?= 0
SERIAL_DEBUG ?= 0
LEGACY_8250_TRACE ?= 0
LEGACY_8250_TRACE_BASE ?= 0x02f8
TTY_DEFAULTS ?= root/etc/default/tty
UART_DEFAULTS ?= root/etc/default/uart
GEM_VDI_DEFAULTS ?= root/etc/default/gem-vdi
# Selected VDI pointer backend (serial/amstrad).  VDISYS opens its workstation
# before FSYS mounts the ext2 root, so its /etc/default/gem-vdi read always uses
# the compiled fallback default; make that default match the selected backend.
GEM_VDI_MOUSE_BACKEND ?= $(shell if [ -r "$(GEM_VDI_DEFAULTS)" ]; then awk -F= 'BEGIN { v="serial" } $$1 == "GEM_VDI_MOUSE_BACKEND" { v=tolower($$2) } END { print v }' "$(GEM_VDI_DEFAULTS)"; else printf serial; fi)
SOUND_DEFAULTS ?= root/etc/default/sound
DRIVER_DEFAULTS ?= root/etc/default/drivers
SERSYS_TTYS0 ?= $(shell if [ -r "$(TTY_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "TTY_ttyS0" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on" || $$2 == "y") v=1 } END { print v }' "$(TTY_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS1 ?= $(shell if [ -r "$(TTY_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "TTY_ttyS1" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on" || $$2 == "y") v=1 } END { print v }' "$(TTY_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS2 ?= $(shell if [ -r "$(TTY_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "TTY_ttyS2" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on" || $$2 == "y") v=1 } END { print v }' "$(TTY_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS3 ?= $(shell if [ -r "$(TTY_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "TTY_ttyS3" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on" || $$2 == "y") v=1 } END { print v }' "$(TTY_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS0_BASE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v="0x3f8" } $$1 == "UART_ttyS0_BASE" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 0x3f8; fi)
SERSYS_TTYS1_BASE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v="0x2f8" } $$1 == "UART_ttyS1_BASE" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 0x2f8; fi)
SERSYS_TTYS2_BASE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v="0x3e8" } $$1 == "UART_ttyS2_BASE" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 0x3e8; fi)
SERSYS_TTYS3_BASE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v="0x2e8" } $$1 == "UART_ttyS3_BASE" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 0x2e8; fi)
SERSYS_TTYS0_TYPE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=255 } $$1 == "UART_ttyS0_TYPE" { if ($$2 == "8250") v=0; else if ($$2 == "16450") v=1; else if ($$2 == "16550") v=2; else if ($$2 == "16550A" || $$2 == "16550a") v=3; else if ($$2 == "16750") v=4; else v=255 } END { print v }' "$(UART_DEFAULTS)"; else printf 255; fi)
SERSYS_TTYS1_TYPE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=255 } $$1 == "UART_ttyS1_TYPE" { if ($$2 == "8250") v=0; else if ($$2 == "16450") v=1; else if ($$2 == "16550") v=2; else if ($$2 == "16550A" || $$2 == "16550a") v=3; else if ($$2 == "16750") v=4; else v=255 } END { print v }' "$(UART_DEFAULTS)"; else printf 255; fi)
SERSYS_TTYS2_TYPE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=255 } $$1 == "UART_ttyS2_TYPE" { if ($$2 == "8250") v=0; else if ($$2 == "16450") v=1; else if ($$2 == "16550") v=2; else if ($$2 == "16550A" || $$2 == "16550a") v=3; else if ($$2 == "16750") v=4; else v=255 } END { print v }' "$(UART_DEFAULTS)"; else printf 255; fi)
SERSYS_TTYS3_TYPE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=255 } $$1 == "UART_ttyS3_TYPE" { if ($$2 == "8250") v=0; else if ($$2 == "16450") v=1; else if ($$2 == "16550") v=2; else if ($$2 == "16550A" || $$2 == "16550a") v=3; else if ($$2 == "16750") v=4; else v=255 } END { print v }' "$(UART_DEFAULTS)"; else printf 255; fi)
SERSYS_IRQ_AWARE ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=1 } $$1 == "UART_DRIVER_MODE" { if ($$2 == "poll" || $$2 == "polling") v=0; else v=1 } END { print v }' "$(UART_DEFAULTS)"; else printf 1; fi)
SERSYS_TTYS0_IRQ ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=4 } $$1 == "UART_ttyS0_IRQ" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 4; fi)
SERSYS_TTYS1_IRQ ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=3 } $$1 == "UART_ttyS1_IRQ" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 3; fi)
SERSYS_TTYS2_IRQ ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=4 } $$1 == "UART_ttyS2_IRQ" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 4; fi)
SERSYS_TTYS3_IRQ ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=3 } $$1 == "UART_ttyS3_IRQ" { v=$$2 } END { print v }' "$(UART_DEFAULTS)"; else printf 3; fi)
SERSYS_TTYS0_FLOW ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "UART_ttyS0_FLOW" { if ($$2 == "rtscts" || $$2 == "hardware" || $$2 == "yes" || $$2 == "1") v=1 } END { print v }' "$(UART_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS1_FLOW ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "UART_ttyS1_FLOW" { if ($$2 == "rtscts" || $$2 == "hardware" || $$2 == "yes" || $$2 == "1") v=1 } END { print v }' "$(UART_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS2_FLOW ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "UART_ttyS2_FLOW" { if ($$2 == "rtscts" || $$2 == "hardware" || $$2 == "yes" || $$2 == "1") v=1 } END { print v }' "$(UART_DEFAULTS)"; else printf 0; fi)
SERSYS_TTYS3_FLOW ?= $(shell if [ -r "$(UART_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "UART_ttyS3_FLOW" { if ($$2 == "rtscts" || $$2 == "hardware" || $$2 == "yes" || $$2 == "1") v=1 } END { print v }' "$(UART_DEFAULTS)"; else printf 0; fi)
SOUND_IRQ_AWARE ?= $(shell if [ -r "$(SOUND_DEFAULTS)" ]; then awk -F= 'BEGIN { v=1 } $$1 == "SOUND_DRIVER_MODE" { if ($$2 == "poll" || $$2 == "polling") v=0; else v=1 } END { print v }' "$(SOUND_DEFAULTS)"; else printf 1; fi)
MFM_ST506_IRQ ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=5 } $$1 == "MFM_ST506_IRQ" { v=$$2 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 5; fi)
MFM_ST506_DMA ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=3 } $$1 == "MFM_ST506_DMA" { v=$$2 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 3; fi)
MFM_IRQ_AWARE ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "MFM_ST506_MODE" { if ($$2 == "irq" || $$2 == "interrupt" || $$2 == "interrupts") v=1; else if ($$2 == "poll" || $$2 == "polling") v=0 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 0; fi)
MFM_DMA_MODE ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "MFM_ST506_DMA_MODE" || $$1 == "MFM_ST506_TRANSFER" { if ($$2 == "yes" || $$2 == "on" || $$2 == "1" || $$2 == "dma") v=1; else if ($$2 == "no" || $$2 == "off" || $$2 == "0" || $$2 == "pio") v=0 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 0; fi)
MFM_DEBUG ?= 0
MFM_TRACE_SECTORS ?= 0
BOOT_USERLAND_DEBUG ?= 0
ASH_SPAWN_TRACE ?= 0
MACHINE_PROFILE ?= pc1640
ifeq ($(GEM_VIDEO_ADAPTER),vga)
GEM_VIDEO_ADAPTER_ID := 0
else ifeq ($(GEM_VIDEO_ADAPTER),ega)
GEM_VIDEO_ADAPTER_ID := 1
else ifeq ($(GEM_VIDEO_ADAPTER),cga)
GEM_VIDEO_ADAPTER_ID := 2
else ifeq ($(GEM_VIDEO_ADAPTER),hercules)
GEM_VIDEO_ADAPTER_ID := 3
else ifeq ($(GEM_VIDEO_ADAPTER),pega)
# PEGA uses the standard EGA planar raster after its PC1640 latch is selected.
GEM_VIDEO_ADAPTER_ID := 1
else
$(error unsupported GEM_VIDEO_ADAPTER=$(GEM_VIDEO_ADAPTER); use vga, ega, cga, hercules, or pega)
endif
ifeq ($(GEM_VIDEO_ADAPTER),pega)
GEM_PC1640_PEGA := 1
ifeq ($(filter $(MACHINE_PROFILE),pc1640 pc1640-dd),)
$(error GEM_VIDEO_ADAPTER=pega requires MACHINE_PROFILE=pc1640 or pc1640-dd)
endif
else
GEM_PC1640_PEGA := 0
ifneq ($(filter $(MACHINE_PROFILE),pc1640 pc1640-dd),)
$(error MACHINE_PROFILE=$(MACHINE_PROFILE) has internal PEGA, so GEM_VIDEO_ADAPTER must be pega)
endif
endif
PROCESS_DEBUG ?= 0
INIT_DEBUG ?= $(PROCESS_DEBUG)
SERSYS_DEBUG ?= $(PROCESS_DEBUG)
FSYS_DEBUG ?= 0
DRIVER_LOG_VERBOSITY ?= 0
SERVER_TRACE_COM2 ?= 0
SERVER_TRACE_COM2_BASE ?= 0x02f8
SERVER_TRACE_COM2_DIVISOR ?= 12
SERVER_TRACE_DEBUG_PORT ?= 0
SERVER_TRACE_DEBUG_PORT_IO ?= 0x00e9
SERVER_TRACE_ENABLED := $(if $(filter 1 yes,$(SERVER_TRACE_COM2) $(SERVER_TRACE_DEBUG_PORT)),1,0)
ENABLE_NETWORK ?= 0
ENABLE_HTTPS ?= 0
START_NETWORK_ON_BOOT ?= 0
START_EXT2FS_ON_BOOT ?= 1
ENABLE_MFM_DRIVER ?= $(if $(filter mfm,$(ROOT_BLOCK_BACKEND)),1,0)
# KERNEL_BLOCK_XTIDE: hybrid target -- the nucleus bootstraps init via firmware
# INT 13h (bios13) but the running kernel's block driver is the in-kernel XTIDE
# PIO path, since driverd executes after the firmware quarantine.  Force the
# ATA/PIO mechanism on and keep bios13 only as the nucleus bootstrap reader.
KERNEL_BLOCK_XTIDE ?= 0
ENABLE_ATA_DRIVER ?= $(if $(filter xtide athd,$(ROOT_BLOCK_BACKEND))$(filter 1,$(KERNEL_BLOCK_XTIDE)),1,0)
ENABLE_BIOS13_DRIVER ?= $(if $(filter bios13,$(ROOT_BLOCK_BACKEND)),1,0)
ENABLE_DIRECTFD_DRIVER ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "DRIVER_DIRECTFD" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on") v=1 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 0; fi)
ENABLE_GAMEPORT_DRIVER ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=0 } $$1 == "DRIVER_GAMEPORT" { if ($$2 == "yes" || $$2 == "1" || $$2 == "on") v=1 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 0; fi)
ENABLE_RAMDISK_DRIVER ?= 0
NET_DRIVER ?= ne2k
NET_PROBE_SELF_TEST ?= 0
NET_NE2K_IO_DEFAULT := 0x0300
ifneq ($(filter $(MACHINE_PROFILE),pc1640-dd qemu),)
NET_NE2K_IO_DEFAULT := 0x0340
endif
NET_NE2K_IO ?= $(NET_NE2K_IO_DEFAULT)
# IRQ3/IRQ4 are the conventional two-port-pair UART lines.  The default XT
# NE2000 therefore uses the otherwise free master-PIC IRQ2 line.
NET_NE2K_IRQ ?= 2
NET_NE2K_BUS ?= auto
NET_NE2K_DEBUG_TX ?= 0
NET_PACKET_PATH ?= 1
NET_COM2_TRACE ?= $(SERVER_TRACE_COM2)
NET_WD80X3_IO ?= 0x0300
NET_WD80X3_IRQ ?= 3
NET_WD80X3_RAM ?= 0xd000
NET_WD80X3_FLAGS ?= 0x90
NET_ULTRA_IO ?= 0x0280
NET_ULTRA_IRQ_DEFAULT := 3
ifeq ($(MACHINE_PROFILE),pc1640-dd)
NET_ULTRA_IRQ_DEFAULT := 2
endif
NET_ULTRA_IRQ ?= $(NET_ULTRA_IRQ_DEFAULT)
NET_ULTRA_RAM ?= 0xd000
NET_ULTRA_FLAGS ?= 0x80
NET_HOSTNAME ?= antler86
NET_IPMODE ?= static
NET_DHCP_ENABLE ?= $(if $(filter dhcp,$(NET_IPMODE)),yes,no)
ENABLE_DHCP_CLIENT ?= $(if $(filter 1 yes YES true TRUE,$(NET_DHCP_ENABLE)),1,0)
NET_DHCP_WAIT ?= 15
NET_LOCALIP ?= 192.168.10.2
NET_GATEWAY ?= 192.168.10.254
NET_NETMASK ?= 255.255.255.0
NET_DNSSERVER ?= 192.168.10.254
NET_EXTRA_HOST_NAME ?=
NET_EXTRA_HOST_IP ?=
NET_LINK_ne2k := ne0
NET_LINK_wd80x3 := wd0
NET_LINK_el3 := 3c0
NET_LINK_ultra := ul0
NET_LINK_83c790qf := ul0
NET_DEVICE_ne2k := /dev/ne0
NET_DEVICE_wd80x3 := /dev/wd0
NET_DEVICE_el3 := /dev/3c0
NET_DEVICE_ultra := /dev/smc0
NET_DEVICE_83c790qf := /dev/smc0
NET_LINK_NAME := $(or $(NET_LINK_$(NET_DRIVER)),ul0)
NET_DEVICE_NAME := $(or $(NET_DEVICE_$(NET_DRIVER)),/dev/eth0)
ifeq ($(ENABLE_NETWORK),1)
ifneq ($(NET_DRIVER),ne2k)
$(error NET_DRIVER=$(NET_DRIVER) is disabled: its user-service driver has no hard-IRQ relay; use ne2k or disable networking)
endif
endif
NTP_ENABLE ?= 0
NTP_SERVER ?= pool.ntp.org
NTP_TIMEOUT ?= 6
NTP_TRIES ?= 3
NTP_LOG ?= /var/log/ntpdate.log
# Ipserial is an optional on-demand login transport (/etc/init.d/ipserial).
# Keeping it out of the boot set leaves netsys demand-started, which the
# 640KB GEM desktop fit depends on; enable it explicitly when wanted.
IPSERIAL_ENABLE ?= 0
IPSERIAL_MODE ?= tcp
IPSERIAL_PORT ?= 23
ENABLE_NFS ?= 0
NFS_START_NETWORK_ON_BOOT ?= $(ENABLE_NFS)
ENABLE_DNS_RESOLVER ?= $(if $(filter 1 yes,$(ENABLE_NFS) $(NTP_ENABLE)),1,0)
ENABLE_LOADABLE_DRIVER_MODULES ?= 1
ENABLE_DRIVER_MODULE_COMPRESSION ?= 0
ENABLE_KERNEL_COMPRESSION ?= 0
FS_ENABLE_FAT_RUNTIME ?= 1
FS_FAT_ENABLE_WRITE ?= 1
FS_ENABLE_EXT2_MOUNT_RUNTIME ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=1 } $$1 == "FS_ENABLE_EXT2_MOUNT_RUNTIME" { if ($$2 == "0" || $$2 == "no" || $$2 == "off" || $$2 == "false") v=0; else v=1 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 1; fi)
# The selected driver defaults may disable only the optional POSIX message
# queue/semaphore service.  The fallback is one, preserving the complete API
# for ordinary and MFM builds whose policy file has no such key.
FS_POSIX_IPC_ENABLE ?= $(shell if [ -r "$(DRIVER_DEFAULTS)" ]; then awk -F= 'BEGIN { v=1 } $$1 == "FS_POSIX_IPC_ENABLE" { if ($$2 == "0" || $$2 == "no" || $$2 == "off" || $$2 == "false") v=0; else v=1 } END { print v }' "$(DRIVER_DEFAULTS)"; else printf 1; fi)
ENABLE_SOUND ?= 0
SOUND_SERVICE_ENABLE ?= 0
START_SOUND_ON_BOOT ?= 0
USERLAND_MEMMODEL ?= small
USERLAND_SERVER_MEMMODEL ?= small
ESD_ENABLE ?= 0
DRIVERD_SOUND_ENABLE ?= $(if $(filter 1 yes,$(ENABLE_SOUND) $(SOUND_SERVICE_ENABLE) $(START_SOUND_ON_BOOT) $(ESD_ENABLE)),1,0)
ESD_PORT ?= 16001
ESD_RATE ?= 22222
ESD_LOG ?= /var/log/esd.log
SOUND_RATE ?= $(ESD_RATE)
SB_PORT ?= 0x220
SB_IRQ ?= 5
SB_DMA ?= 1
SOUND_DRIVER ?= sb
ifeq ($(SOUND_DRIVER),pcspk)
SOUND_DRIVER := pcspeaker
endif
ifeq ($(filter $(SOUND_DRIVER),sb pcspeaker),)
$(error unsupported SOUND_DRIVER=$(SOUND_DRIVER); use sb or pcspeaker)
endif
SOUND_DRIVER_SB := $(if $(filter sb,$(SOUND_DRIVER)),1,0)
SOUND_DRIVER_PCSPEAKER := $(if $(filter pcspeaker,$(SOUND_DRIVER)),1,0)
# /etc/default/sound records the short canonical pcspk spelling; the MartyPC
# session harness and the build accept only that form in the installed file.
SOUND_DRIVER_FILE := $(if $(filter pcspeaker,$(SOUND_DRIVER)),pcspk,$(SOUND_DRIVER))
SOUND_OPTI_SB_MODE ?= off
SOUND_OPTI_SB_PORT ?=
SOUND_OPTI_SB_IRQ ?=
SOUND_OPTI_SB_DMA ?=
NFS_SERVER ?= hulk
NFS_SERVER_IP ?=
NFS_EXPORT ?= /mnt/srv/Antler
NFS_MOUNTPOINT ?= /mnt/nfs
NFS_TEST_ROOT ?= $(NFS_MOUNTPOINT)
NFS_DEVICE ?= /dev/eth0
NFS_PORT ?= 2049
NFS_MOUNT_PORT ?= 0
NFS_TIMEOUT_TICKS ?= 200
NFS_RETRIES ?= 3
NETSTACK_RX_BYTES ?= 256
NFS_FRAME_BYTES ?= 320
KERNEL_NFS_DATA_BYTES ?= 128
KERNEL_NETSTACK_IP_MTU ?= 320
KERNEL_NETSTACK_TCP_MSS ?= 128
KERNEL_NETSTACK_SOCKETS ?= 10
KERNEL_NETSTACK_ARP_ENTRIES ?= 2

MACHINE_PROFILES := pcxt pc1640 pc1640-dd tandy video7 qemu
ifeq ($(filter $(MACHINE_PROFILE),$(MACHINE_PROFILES)),)
$(error unsupported MACHINE_PROFILE=$(MACHINE_PROFILE); use pcxt, pc1640, pc1640-dd, tandy, video7, or qemu)
endif

ROOT_BLOCK_BACKENDS := mfm xtide athd bios13
ROOT_BLOCK_BACKEND_UPPER_mfm := MFM
ROOT_BLOCK_BACKEND_UPPER_xtide := XTIDE
ROOT_BLOCK_BACKEND_UPPER_athd := ATHD
ROOT_BLOCK_BACKEND_UPPER_bios13 := BIOS13
ROOT_BLOCK_BACKEND_UPPER := $(ROOT_BLOCK_BACKEND_UPPER_$(ROOT_BLOCK_BACKEND))
ifeq ($(filter $(ROOT_BLOCK_BACKEND),$(ROOT_BLOCK_BACKENDS)),)
$(error unsupported ROOT_BLOCK_BACKEND=$(ROOT_BLOCK_BACKEND); use mfm, ide/xtide, athd, or bios13)
endif

IA16_MEMMODELS := tiny small medium compact large huge
IA16_NEAR_DATA_MODELS := tiny small medium
ifeq ($(filter $(USERLAND_MEMMODEL),$(IA16_MEMMODELS)),)
$(error unsupported USERLAND_MEMMODEL=$(USERLAND_MEMMODEL); use tiny, small, medium, compact, large, or huge)
endif
ifeq ($(filter $(USERLAND_SERVER_MEMMODEL),$(IA16_MEMMODELS)),)
$(error unsupported USERLAND_SERVER_MEMMODEL=$(USERLAND_SERVER_MEMMODEL); use tiny, small, medium, compact, large, or huge)
endif
ifeq ($(ENABLE_RAMDISK_DRIVER),1)
ifeq ($(filter $(USERLAND_MEMMODEL),$(IA16_NEAR_DATA_MODELS)),)
$(error ramdisk-smoke requires a near-data USERLAND_MEMMODEL; use tiny, small, or medium)
endif
ifeq ($(filter $(USERLAND_SERVER_MEMMODEL),$(IA16_NEAR_DATA_MODELS)),)
$(error ramdiskd requires a near-data USERLAND_SERVER_MEMMODEL; use tiny, small, or medium)
endif
endif
USERLAND_MEMMODEL_CODE_tiny := T
USERLAND_MEMMODEL_CODE_small := S
USERLAND_MEMMODEL_CODE_medium := M
USERLAND_MEMMODEL_CODE_compact := C
USERLAND_MEMMODEL_CODE_large := L
USERLAND_MEMMODEL_CODE_huge := H
USERLAND_MEMMODEL_CODE := $(USERLAND_MEMMODEL_CODE_$(USERLAND_MEMMODEL))
USERLAND_SERVER_MEMMODEL_CODE := $(USERLAND_MEMMODEL_CODE_$(USERLAND_SERVER_MEMMODEL))

CC := $(CROSS)gcc
LD := $(CROSS)ld
AR := $(CROSS)ar
OBJCOPY := $(CROSS)objcopy
OBJDUMP := $(CROSS)objdump
NM := $(CROSS)nm
HOSTCC ?= cc
HOSTCFLAGS ?= -O2 -Wall -Wextra -I$(PROJECT_ROOT)/kern
GCC_INCLUDE_DIR := $(shell $(CC) -print-file-name=include)
NATIVE_LIBGCC := $(TOOLCHAIN_DIR)/cross/lib/gcc/ia16-elf/6.3.0/libgcc.a
NO_BIOS_AUDIT := $(PROJECT_ROOT)/scripts/audit-no-bios-runtime.py
# The bios13 backend intentionally issues INT 13h from driverd, so its userland
# images are exempt from the runtime no-BIOS audit (every other backend keeps
# it as a hard build step).
ifeq ($(ROOT_BLOCK_BACKEND),bios13)
NO_BIOS_AUDIT_RUN := true
else
NO_BIOS_AUDIT_RUN := $(PYTHON) $(NO_BIOS_AUDIT) --repo $(PROJECT_ROOT) --tool-prefix $(CROSS)
endif
LDFLAGS ?= --gc-sections -q

CPPFLAGS := -I../kern -I../kern/system -I$(SERVER_SRC_ROOT) -I..
CPPFLAGS += -I.
CPPFLAGS += -nostdinc -Ilibc/include -Ilibc -isystem $(GCC_INCLUDE_DIR)
CPPFLAGS += -DANTLER_KERNEL_MEMMODEL_NAME=\"small\"
CPPFLAGS += -DANTLER_KERNEL_MEMMODEL_CODE=\"S\"
CPPFLAGS += -DANTLER_NATIVE_MEMMODEL_NAME=\"$(USERLAND_MEMMODEL)\"
CPPFLAGS += -DANTLER_NATIVE_MEMMODEL_CODE=\"$(USERLAND_MEMMODEL_CODE)\"
CPPFLAGS += -DANTLER_SERVER_MEMMODEL_NAME=\"$(USERLAND_SERVER_MEMMODEL)\"
CPPFLAGS += -DANTLER_SERVER_MEMMODEL_CODE=\"$(USERLAND_SERVER_MEMMODEL_CODE)\"
CPPFLAGS += -DANTLER_MAX_PORTS=$(KERNEL_MAX_PORTS)
CPPFLAGS += -DANTLER_MAX_TASKS=$(KERNEL_MAX_TASKS)
CPPFLAGS += -DANTLER_MAX_USER_PROCS=$(KERNEL_MAX_USER_PROCS)
CPPFLAGS += -DANTLER_MAX_SOCK_ADDR=$(KERNEL_MAX_SOCK_ADDR)
CPPFLAGS += -DANTLER_UNIX_PATH_MAX=$(KERNEL_UNIX_PATH_MAX)
CPPFLAGS += -DANTLER_KLOG_BUFFER_BYTES=$(KLOG_BUFFER_BYTES)
CPPFLAGS += -DANTLER_UTS_SYSNAME=\"$(KERNEL_UTS_SYSNAME)\"
CPPFLAGS += -DANTLER_UTS_NODENAME=\"$(KERNEL_UTS_NODENAME)\"
CPPFLAGS += -DANTLER_UTS_RELEASE=\"$(KERNEL_UTS_RELEASE)\"
CPPFLAGS += -DANTLER_UTS_VERSION=\"$(KERNEL_UTS_VERSION)\"
CPPFLAGS += -DANTLER_UTS_MACHINE=\"$(KERNEL_UTS_MACHINE)\"
CPPFLAGS += -DANX_NATIVE_MOUNT_MAX=$(KERNEL_NATIVE_MOUNT_MAX)
CPPFLAGS += -DANTLER_ROOT_BLOCK_BACKEND_NAME=\"$(ROOT_BLOCK_BACKEND)\"
CPPFLAGS += -DANTLER_ROOT_BLOCK_BACKEND_$(ROOT_BLOCK_BACKEND_UPPER)=1
CPPFLAGS += -DANTLER_XTIDE_IO=$(USERLAND_XTIDE_IO_LITERAL)
CPPFLAGS += -DANTLER_LPT_BASE=$(ANTLER_LPT_BASE)
CPPFLAGS += -DANTLER_GEM_VIDEO_ADAPTER=$(GEM_VIDEO_ADAPTER_ID)
# Only the PC1640 motherboard owns the Paradise PEGA extended latch ports.
# External EGA cards share PEGA's raster registers but must never receive its
# motherboard-specific two-read latch transaction.
CPPFLAGS += -DANTLER_GEM_PC1640_PEGA=$(GEM_PC1640_PEGA)
ifneq ($(filter $(GEM_VDI_MOUSE_BACKEND),amstrad pc1512 pc1640),)
CPPFLAGS += -DANTLER_GEM_VDI_MOUSE_DEFAULT_AMSTRAD=1
endif
BOOT_ARCHIVE_BASE_SECTOR ?= 8192
CPPFLAGS += -DANTLER_BOOT_ARCHIVE_BASE_SECTOR=$(BOOT_ARCHIVE_BASE_SECTOR)u
CPPFLAGS += -DANTLER_BOOT_GEOM_SECT=$(BOOT_GEOM_SECT)u
CPPFLAGS += -DANTLER_BOOT_GEOM_HEAD=$(BOOT_GEOM_HEAD)u
CPPFLAGS += -DANTLER_BOOT_GEOM_CYL=$(BOOT_GEOM_CYL)u
CPPFLAGS += -DANTLER_BOOT_IMAGE_SECTORS=$(USERLAND_HD_IMAGE_SECTORS)u
CPPFLAGS += -DANTLER_MACHINE_PROFILE_NAME=\"$(MACHINE_PROFILE)\"
CPPFLAGS += -DANTLER_NET_DRIVER_NAME=\"$(NET_DRIVER)\"
CPPFLAGS += -DANTLER_NET_LINK_NAME=\"$(NET_LINK_NAME)\"
CPPFLAGS += -DANTLER_NET_DEVICE_NAME=\"$(NET_DEVICE_NAME)\"
CPPFLAGS += -DANTLER_NET_HOSTNAME=\"$(NET_HOSTNAME)\"
CPPFLAGS += -DANTLER_NET_DHCP_WAIT=$(NET_DHCP_WAIT)
CPPFLAGS += -DANTLER_NET_LOCALIP=\"$(NET_LOCALIP)\"
CPPFLAGS += -DANTLER_NET_GATEWAY=\"$(NET_GATEWAY)\"
CPPFLAGS += -DANTLER_NET_NETMASK=\"$(NET_NETMASK)\"
CPPFLAGS += -DANTLER_NET_DNSSERVER=\"$(NET_DNSSERVER)\"
CPPFLAGS += -DANTLER_IPSERIAL_ENABLE=$(if $(filter 1 yes,$(IPSERIAL_ENABLE)),1,0)
CPPFLAGS += -DANTLER_IPSERIAL_MODE_TCP=$(if $(filter tcp TCP,$(IPSERIAL_MODE)),1,0)
CPPFLAGS += -DANTLER_IPSERIAL_PORT=$(IPSERIAL_PORT)
CPPFLAGS += -DANTLER_NTP_ENABLE=$(if $(filter 1 yes,$(NTP_ENABLE)),1,0)
CPPFLAGS += -DANTLER_START_NETWORK_ON_BOOT=$(if $(filter 1 yes,$(START_NETWORK_ON_BOOT)),1,0)
CPPFLAGS += -DANTLER_START_EXT2FS_ON_BOOT=$(if $(filter 1 yes,$(START_EXT2FS_ON_BOOT)),1,0)
CPPFLAGS += -DANTLER_NETSTACK_RX_BYTES=$(NETSTACK_RX_BYTES)
CPPFLAGS += -DANTLER_NETSTACK_IP_MTU=$(KERNEL_NETSTACK_IP_MTU)
CPPFLAGS += -DANTLER_NETSTACK_TCP_MSS=$(KERNEL_NETSTACK_TCP_MSS)
CPPFLAGS += -DANTLER_NETSTACK_SOCKETS=$(KERNEL_NETSTACK_SOCKETS)
CPPFLAGS += -DANTLER_NETSTACK_ARP_ENTRIES=$(KERNEL_NETSTACK_ARP_ENTRIES)
CPPFLAGS += -DANTLER_ESD_RATE=\"$(ESD_RATE)\"
CPPFLAGS += -DANTLER_SOUND_SB_PORT=$(SB_PORT)
CPPFLAGS += -DANTLER_SOUND_SB_IRQ=$(SB_IRQ)
CPPFLAGS += -DANTLER_SOUND_SB_DMA=$(SB_DMA)
CPPFLAGS += -DANTLER_ENABLE_SOUND_DRIVER=$(DRIVERD_SOUND_ENABLE)
CPPFLAGS += -DANTLER_SOUND_IRQ_AWARE=$(SOUND_IRQ_AWARE)
CPPFLAGS += -DANTLER_SOUND_DRIVER_SB=$(SOUND_DRIVER_SB)
CPPFLAGS += -DANTLER_SOUND_DRIVER_PCSPEAKER=$(SOUND_DRIVER_PCSPEAKER)
CPPFLAGS += -DCONFIG_SB_PORT=$(SB_PORT)
CPPFLAGS += -DCONFIG_SB_IRQ=$(SB_IRQ)
CPPFLAGS += -DCONFIG_SB_DMA=$(SB_DMA)
CPPFLAGS += -DANTLER_ENABLE_MFM_DRIVER=$(if $(filter 1 yes,$(ENABLE_MFM_DRIVER)),1,0)
CPPFLAGS += -DANTLER_ENABLE_ATA_DRIVER=$(if $(filter 1 yes,$(ENABLE_ATA_DRIVER)),1,0)
CPPFLAGS += -DANTLER_ENABLE_BIOS13_DRIVER=$(if $(filter 1 yes,$(ENABLE_BIOS13_DRIVER)),1,0)
CPPFLAGS += -DANTLER_KERNEL_BLOCK_XTIDE=$(if $(filter 1 yes,$(KERNEL_BLOCK_XTIDE)),1,0)
CPPFLAGS += -DANTLER_ENABLE_DIRECTFD_DRIVER=$(if $(filter 1 yes,$(ENABLE_DIRECTFD_DRIVER)),1,0)
CPPFLAGS += -DANTLER_ENABLE_GAMEPORT_DRIVER=$(if $(filter 1 yes,$(ENABLE_GAMEPORT_DRIVER)),1,0)
CPPFLAGS += -DFS_ENABLE_FAT_RUNTIME=$(if $(filter 1 yes,$(FS_ENABLE_FAT_RUNTIME)),1,0)
CPPFLAGS += -DFS_FAT_ENABLE_WRITE=$(if $(filter 1 yes,$(FS_FAT_ENABLE_WRITE)),1,0)
CPPFLAGS += -DFS_ENABLE_EXT2_MOUNT_RUNTIME=$(if $(filter 1 yes,$(FS_ENABLE_EXT2_MOUNT_RUNTIME)),1,0)
CPPFLAGS += -DFS_POSIX_IPC_ENABLE=$(if $(filter 1 yes,$(FS_POSIX_IPC_ENABLE)),1,0)
CPPFLAGS += -DANTLER_MFM_ST506_IRQ=$(MFM_ST506_IRQ)
CPPFLAGS += -DANTLER_MFM_ST506_DMA=$(MFM_ST506_DMA)
CPPFLAGS += -DANTLER_MFM_IRQ_AWARE=$(MFM_IRQ_AWARE)
CPPFLAGS += -DANTLER_MFM_DMA_MODE=$(MFM_DMA_MODE)
ifeq ($(MFM_DEBUG),1)
CPPFLAGS += -DANTLER_MFM_VERBOSE_DEBUG=1
CPPFLAGS += -DANX_MFM_VERBOSE_DEBUG=1
endif
ifeq ($(MFM_TRACE_SECTORS),1)
CPPFLAGS += -DANTLER_MFM_TRACE_SECTORS=1
CPPFLAGS += -DANX_MFM_TRACE_SECTORS=1
endif
CPPFLAGS += -DANTLER_ENABLE_NFS=$(if $(filter 1 yes,$(ENABLE_NFS)),1,0)
CPPFLAGS += -DANTLER_NFS_SERVER=\"$(NFS_SERVER)\"
CPPFLAGS += -DANTLER_NFS_SERVER_IP=\"$(NFS_SERVER_IP)\"
CPPFLAGS += -DANTLER_NFS_EXPORT=\"$(NFS_EXPORT)\"
CPPFLAGS += -DANTLER_NFS_MOUNTPOINT=\"$(NFS_MOUNTPOINT)\"
CPPFLAGS += -DANTLER_NFS_TEST_ROOT=\"$(NFS_TEST_ROOT)\"
CPPFLAGS += -DANTLER_NFS_DEVICE=\"$(NET_DEVICE_NAME)\"
CPPFLAGS += -DANTLER_NFS_FRAME_BYTES=$(NFS_FRAME_BYTES)
CPPFLAGS += -DANTLER_NFS_DATA_BYTES=$(KERNEL_NFS_DATA_BYTES)
CPPFLAGS += -DANTLER_ROOT_DEVICE=\"$(ROOT_DEVICE)\"
CPPFLAGS += -DANTLER_ROOT_FS_TYPE=\"$(ROOT_FS_TYPE)\"
CPPFLAGS += -DANTLER_ROOT_FLAGS=\"$(ROOT_FLAGS)\"
CPPFLAGS += -DANTLER_NFS_PORT=\"$(NFS_PORT)\"
CPPFLAGS += -DANTLER_NFS_MOUNT_PORT=\"$(NFS_MOUNT_PORT)\"
CPPFLAGS += -DANTLER_NFS_TIMEOUT_TICKS=\"$(NFS_TIMEOUT_TICKS)\"
CPPFLAGS += -DANTLER_NFS_RETRIES=\"$(NFS_RETRIES)\"
CPPFLAGS += -DANTLER_PROCESS_DEBUG=$(PROCESS_DEBUG)
# The mounted-exec trace lives in the nfs service and the verbose ext2 trace
# in the ext2fs service; both build here, so their knobs must be delivered
# here, not only in the kernel CPPFLAGS.
MOUNTED_EXEC_TRACE ?= 0
EXT2_DEBUG ?= 0
# network_stack/{core/stack.c,transport/tcp.c} gate their entry tracing on
# ANX_ENTRY_TRACE and build in this Makefile, so the knob is delivered here
# as well as in the kernel CPPFLAGS.
ENTRY_TRACE ?= 0
CPPFLAGS += -DANX_ENTRY_TRACE=$(ENTRY_TRACE)
CPPFLAGS += -DANTLER_MOUNTED_EXEC_TRACE=$(MOUNTED_EXEC_TRACE)
ifeq ($(EXT2_DEBUG),1)
CPPFLAGS += -DANTLER_EXT2_VERBOSE_DEBUG=1
endif
CPPFLAGS += -DANTLER_INIT_DEBUG=$(INIT_DEBUG)
CPPFLAGS += -DANTLER_SERSYS_DEBUG=$(SERSYS_DEBUG)
CPPFLAGS += -DANTLER_FSYS_DEBUG=$(FSYS_DEBUG)
CPPFLAGS += -DANX_DRIVER_LOG_VERBOSITY=$(DRIVER_LOG_VERBOSITY)
CPPFLAGS += -DANTLER_SERVER_TRACE_COM2=$(SERVER_TRACE_COM2)
CPPFLAGS += -DANTLER_SERVER_TRACE_COM2_BASE=$(SERVER_TRACE_COM2_BASE)u
CPPFLAGS += -DANTLER_SERVER_TRACE_COM2_DIVISOR=$(SERVER_TRACE_COM2_DIVISOR)u
CPPFLAGS += -DANTLER_SERVER_TRACE_DEBUG_PORT=$(SERVER_TRACE_DEBUG_PORT)
CPPFLAGS += -DANTLER_SERVER_TRACE_DEBUG_PORT_IO=$(SERVER_TRACE_DEBUG_PORT_IO)u
CPPFLAGS += -DANTLER_NATIVE_MAX_NODES=$(KERNEL_NATIVE_MAX_NODES)
CPPFLAGS += -DANTLER_FSYS_MAX_FDS=$(FSYS_MAX_FDS)
CPPFLAGS += -DANTLER_FSYS_MAX_NODES=$(FSYS_MAX_NODES)
CPPFLAGS += -DANTLER_FSYS_MAX_MOUNTS=$(FSYS_MAX_MOUNTS)
CPPFLAGS += -DANTLER_FSYS_PTYS=$(FSYS_PTYS)
CPPFLAGS += -DANTLER_FSYS_PTY_BUF_BYTES=$(FSYS_PTY_BUF_BYTES)
CPPFLAGS += -DANTLER_KERNEL_DEBUG_TTY=$(KERNEL_DEBUG_TTY)
CPPFLAGS += -DANTLER_SERIAL_DEBUG=$(SERIAL_DEBUG)
CPPFLAGS += -DANTLER_LEGACY_8250_TRACE=$(LEGACY_8250_TRACE)
CPPFLAGS += -DANTLER_LEGACY_8250_TRACE_BASE=$(LEGACY_8250_TRACE_BASE)
CPPFLAGS += -DANTLER_SERSYS_TTYS0=$(SERSYS_TTYS0)
CPPFLAGS += -DANTLER_SERSYS_TTYS1=$(SERSYS_TTYS1)
CPPFLAGS += -DANTLER_SERSYS_TTYS2=$(SERSYS_TTYS2)
CPPFLAGS += -DANTLER_SERSYS_TTYS3=$(SERSYS_TTYS3)
CPPFLAGS += -DANTLER_SERSYS_TTYS0_BASE=$(SERSYS_TTYS0_BASE)
CPPFLAGS += -DANTLER_SERSYS_TTYS1_BASE=$(SERSYS_TTYS1_BASE)
CPPFLAGS += -DANTLER_SERSYS_TTYS2_BASE=$(SERSYS_TTYS2_BASE)
CPPFLAGS += -DANTLER_SERSYS_TTYS3_BASE=$(SERSYS_TTYS3_BASE)
CPPFLAGS += -DANTLER_SERSYS_TTYS0_TYPE=$(SERSYS_TTYS0_TYPE)
CPPFLAGS += -DANTLER_SERSYS_TTYS1_TYPE=$(SERSYS_TTYS1_TYPE)
CPPFLAGS += -DANTLER_SERSYS_TTYS2_TYPE=$(SERSYS_TTYS2_TYPE)
CPPFLAGS += -DANTLER_SERSYS_TTYS3_TYPE=$(SERSYS_TTYS3_TYPE)
CPPFLAGS += -DANTLER_SERSYS_IRQ_AWARE=$(SERSYS_IRQ_AWARE)
CPPFLAGS += -DANTLER_SERSYS_TTYS0_IRQ=$(SERSYS_TTYS0_IRQ)
CPPFLAGS += -DANTLER_SERSYS_TTYS1_IRQ=$(SERSYS_TTYS1_IRQ)
CPPFLAGS += -DANTLER_SERSYS_TTYS2_IRQ=$(SERSYS_TTYS2_IRQ)
CPPFLAGS += -DANTLER_SERSYS_TTYS3_IRQ=$(SERSYS_TTYS3_IRQ)
CPPFLAGS += -DANTLER_SERSYS_TTYS0_FLOW=$(SERSYS_TTYS0_FLOW)
CPPFLAGS += -DANTLER_SERSYS_TTYS1_FLOW=$(SERSYS_TTYS1_FLOW)
CPPFLAGS += -DANTLER_SERSYS_TTYS2_FLOW=$(SERSYS_TTYS2_FLOW)
CPPFLAGS += -DANTLER_SERSYS_TTYS3_FLOW=$(SERSYS_TTYS3_FLOW)
CPPFLAGS += -DANTLER_BOOT_USERLAND_DEBUG=$(BOOT_USERLAND_DEBUG)
ifeq ($(ENABLE_NETWORK),1)
ifeq ($(NET_PACKET_PATH),1)
CPPFLAGS += -DANTLER_NET_PACKET_PATH=1
CPPFLAGS += -DANX_NET_PACKET_PATH=1
endif
# Physical NE2K hardware uses the privileged coalesced hard-IRQ relay.
CPPFLAGS += -DANTLER_NET_POLLING_ONLY=0
CPPFLAGS += -DANX_NET_USER_IRQ_RELAY=1
CPPFLAGS += -DANTLER_NET_NE2K_IO=$(NET_NE2K_IO)
CPPFLAGS += -DANTLER_NET_NE2K_IRQ=$(NET_NE2K_IRQ)
CPPFLAGS += -DANTLER_NET_NE2K_DEBUG_TX=$(NET_NE2K_DEBUG_TX)
CPPFLAGS += -DANTLER_NET_COM2_TRACE=$(NET_COM2_TRACE)
CPPFLAGS += -DANTLER_NET_WD80X3_IO=$(NET_WD80X3_IO)
CPPFLAGS += -DANTLER_NET_WD80X3_IRQ=$(NET_WD80X3_IRQ)
CPPFLAGS += -DANTLER_NET_WD80X3_RAM=$(NET_WD80X3_RAM)
CPPFLAGS += -DANTLER_NET_WD80X3_FLAGS=$(NET_WD80X3_FLAGS)
CPPFLAGS += -DANTLER_NET_ULTRA_IO=$(NET_ULTRA_IO)
CPPFLAGS += -DANTLER_NET_ULTRA_IRQ=$(NET_ULTRA_IRQ)
CPPFLAGS += -DANTLER_NET_ULTRA_RAM=$(NET_ULTRA_RAM)
CPPFLAGS += -DANTLER_NET_ULTRA_FLAGS=$(NET_ULTRA_FLAGS)
ifeq ($(NET_DRIVER),ne2k)
CPPFLAGS += -DANTLER_NET_BUILD_NE2K=1
ifeq ($(NET_NE2K_BUS),8)
CPPFLAGS += -DANTLER_NET_NE2K_FORCE_8BIT=1
else ifeq ($(NET_NE2K_BUS),16)
CPPFLAGS += -DANTLER_NET_NE2K_FORCE_16BIT=1
else ifneq ($(NET_NE2K_BUS),auto)
$(error unsupported NET_NE2K_BUS=$(NET_NE2K_BUS); use auto, 8, or 16)
endif
else ifeq ($(NET_DRIVER),wd80x3)
CPPFLAGS += -DANTLER_NET_BUILD_WD80X3=1
else ifeq ($(NET_DRIVER),el3)
CPPFLAGS += -DANTLER_NET_BUILD_EL3=1
else ifeq ($(NET_DRIVER),83c790qf)
CPPFLAGS += -DANTLER_NET_BUILD_83C790QF=1
else ifeq ($(NET_DRIVER),ultra)
CPPFLAGS += -DANTLER_NET_BUILD_83C790QF=1
CPPFLAGS += -DANTLER_NET_DRIVER_ULTRA_ALIAS=1
else
$(error unsupported NET_DRIVER=$(NET_DRIVER); use ne2k)
endif
endif
CPPFLAGS += $(patsubst -DANTLER_%,-DANX_%,\
	$(filter-out -DANTLER_ROOT_BLOCK_BACKEND%,\
	$(filter -DANTLER_%,$(CPPFLAGS))))
CPPFLAGS += -DENABLE_NETWORK=$(ENABLE_NETWORK)
CPPFLAGS += -DENABLE_SOUND=$(ENABLE_SOUND)
ifeq ($(ENABLE_DHCP_CLIENT),1)
CPPFLAGS += -DANX_NET_DHCP_CLIENT=1
endif
ifeq ($(ENABLE_DNS_RESOLVER),1)
CPPFLAGS += -DANX_NET_DNS_RESOLVER=1
endif
CFLAGS_COMMON := $(CPPFLAGS) -std=gnu99 -Os -Wall -Wextra
CFLAGS_COMMON += -DANTLER_USERLAND_16BIT_ONLY=1 -D__HAS_NO_LONGLONG__ -Dlong=short
CFLAGS_COMMON += -ffreestanding -fno-builtin -fno-pic -fno-stack-protector
CFLAGS_COMMON += -fno-jump-tables -ffunction-sections -fdata-sections
CFLAGS_COMMON += -fno-omit-frame-pointer
CFLAGS_COMMON += -march=i8086 -mtune=i8086 -mno-protected-mode
CFLAGS_COMMON += -msegelf
IA16_NEAR_SEG_RELOC_MODELS := tiny small
IA16_FAR_TEXT_MODELS := medium large huge
USERLAND_SEG_RELOC_FLAG := $(if $(filter $(USERLAND_MEMMODEL),$(IA16_NEAR_SEG_RELOC_MODELS)),-mno-segment-relocation-stuff,)
SERVER_SEG_RELOC_FLAG := $(if $(filter $(USERLAND_SERVER_MEMMODEL),$(IA16_NEAR_SEG_RELOC_MODELS)),-mno-segment-relocation-stuff,)
CFLAGS := $(CFLAGS_COMMON) -mcmodel=$(USERLAND_MEMMODEL) $(USERLAND_SEG_RELOC_FLAG)
SERVER_CFLAGS := $(CFLAGS_COMMON) -mcmodel=$(USERLAND_SERVER_MEMMODEL) $(SERVER_SEG_RELOC_FLAG)
BUILD_CONFIG := $(BUILD)/.config.stamp

NATIVE_SMALL_LD := native/native.ld
NATIVE_FAR_TEXT_LD := native/native_medium.ld
NATIVE_LD := $(if $(filter $(USERLAND_MEMMODEL),$(IA16_FAR_TEXT_MODELS)),$(NATIVE_FAR_TEXT_LD),$(NATIVE_SMALL_LD))
SERVER_LD := $(if $(filter $(USERLAND_SERVER_MEMMODEL),$(IA16_FAR_TEXT_MODELS)),$(NATIVE_FAR_TEXT_LD),$(NATIVE_SMALL_LD))
NATIVE_MEDIUM_LD := $(NATIVE_FAR_TEXT_LD)
MKBOOTAR := $(BUILD)/tools/mkbootar
MKANTLER := $(BUILD)/tools/mkantler
ARCHIVE := $(BUILD)/antler.uar
FULL_ARCHIVE := $(BUILD)/antler-full.uar
ROOTFS_DEBUGFS_SCRIPT ?= $(BUILD)/rootfs.debugfs
ARCHIVE_EXTRA_DEPS ?=
ARCHIVE_EXTRA_ARGS ?=
INIT_BIN ?= $(BUILD)/bin/antler-init
ROOT_ARCHIVE_EXCLUDE ?=

ROOT_GENERATED_FILES := \
	$(BUILD)/root/config/sys.init \
	$(BUILD)/root/boot/cmdline \
	$(BUILD)/root/etc/fstab \
	$(BUILD)/root/etc/inittab \
	$(BUILD)/root/etc/rc.sys \
	$(BUILD)/root/etc/default/kernel \
	$(BUILD)/root/etc/default/drivers \
	$(BUILD)/root/etc/default/rcS \
	$(BUILD)/root/etc/default/root \
	$(BUILD)/root/etc/default/sound \
	$(BUILD)/root/etc/default/tty \
	$(BUILD)/root/etc/default/uart \
	$(BUILD)/root/etc/default/gem-vdi \
	$(BUILD)/root/etc/services.conf \
	$(BUILD)/root/etc/ipserial.conf
ifeq ($(ENABLE_NETWORK),1)
ROOT_GENERATED_FILES += \
	$(BUILD)/root/etc/network/interfaces \
	$(BUILD)/root/etc/hosts \
	$(BUILD)/root/etc/resolv.conf
endif
ROOT_NETWORK_SKIP :=
ifeq ($(ENABLE_NETWORK),0)
ROOT_NETWORK_SKIP := \
	root/bin/net \
	root/bin/setup \
	root/etc/network/interfaces \
	root/etc/hosts \
	root/etc/resolv.conf
endif
ROOT_DRIVER_MODULE_SKIP :=
ifeq ($(ENABLE_LOADABLE_DRIVER_MODULES),0)
ROOT_DRIVER_MODULE_SKIP := $(shell find root/system/drivers -type f | sort)
else
# Retain these imported sources for provenance, but do not advertise hardware
# profiles which lack the required user-service hard-IRQ relay.
ROOT_DRIVER_MODULE_SKIP := \
	root/system/drivers/83c790qf \
	root/system/drivers/el3 \
	root/system/drivers/wd80x3
endif
ROOT_ARCHIVE_SKIP := \
	root/bin/sys \
	root/config/sys.init \
	root/boot/cmdline \
	root/etc/fstab \
	root/etc/inittab \
	root/etc/rc.sys \
	root/etc/default/kernel \
	root/etc/default/drivers \
	root/etc/network/interfaces \
	root/etc/hosts \
	root/etc/resolv.conf \
	root/etc/default/rcS \
	root/etc/default/root \
	root/etc/default/sound \
	root/etc/default/tty \
	root/etc/default/uart \
	root/etc/default/gem-vdi \
	root/etc/services.conf \
	root/etc/ipserial.conf \
	$(ROOT_NETWORK_SKIP) \
	$(ROOT_DRIVER_MODULE_SKIP) \
	$(ROOT_ARCHIVE_EXCLUDE)
ROOT_ARCHIVE_FILES := \
	$(filter-out $(ROOT_ARCHIVE_SKIP),$(shell find root -type f ! -name '.*' | sort)) \
	$(filter-out $(ROOT_ARCHIVE_SKIP),$(shell find root/home root/root -type f \( -name '.profile' -o -name '.ashrc' -o -name '.bashrc' \) | sort))
ROOT_ARCHIVE_ARGS := $(foreach file,$(ROOT_ARCHIVE_FILES),$(patsubst root/%,%,$(file))=$(CURDIR)/$(file))
ROOT_ARCHIVE_ARGS += \
	config/sys.init=$(BUILD)/root/config/sys.init \
	boot/cmdline=$(BUILD)/root/boot/cmdline \
	etc/fstab=$(BUILD)/root/etc/fstab \
	etc/inittab=$(BUILD)/root/etc/inittab \
	etc/rc.sys=$(BUILD)/root/etc/rc.sys \
	etc/perror=$(CURDIR)/root/system/share/perror \
	etc/default/kernel=$(BUILD)/root/etc/default/kernel \
	etc/default/drivers=$(BUILD)/root/etc/default/drivers \
	etc/default/rcS=$(BUILD)/root/etc/default/rcS \
	etc/default/root=$(BUILD)/root/etc/default/root \
	etc/default/sound=$(BUILD)/root/etc/default/sound \
	etc/default/tty=$(BUILD)/root/etc/default/tty \
	etc/default/uart=$(BUILD)/root/etc/default/uart \
	etc/default/gem-vdi=$(BUILD)/root/etc/default/gem-vdi \
	etc/services.conf=$(BUILD)/root/etc/services.conf \
	etc/ipserial.conf=$(BUILD)/root/etc/ipserial.conf
ifeq ($(ENABLE_NETWORK),1)
ROOT_ARCHIVE_ARGS += \
	etc/network/interfaces=$(BUILD)/root/etc/network/interfaces \
	etc/hosts=$(BUILD)/root/etc/hosts \
	etc/resolv.conf=$(BUILD)/root/etc/resolv.conf
endif
HD_ROOT_NETWORK_SKIP :=
HD_ROOT_GENERATED_FILES :=
HD_ROOT_GENERATED_ARGS :=
HD_ROOT_ARCHIVE_FILES := \
	$(filter-out $(HD_ROOT_NETWORK_SKIP),$(shell if [ -d hdroot ]; then find hdroot -type f | sort; fi))
HD_ROOT_ARCHIVE_ARGS := $(foreach file,$(HD_ROOT_ARCHIVE_FILES),$(patsubst hdroot/%,%,$(file))=$(CURDIR)/$(file))
HD_ROOT_ARCHIVE_ARGS += $(HD_ROOT_GENERATED_ARGS)

NATIVE_BASE_LIB_OBJS := \
	$(BUILD)/native/null_data.o \
	$(BUILD)/native/libanx/anx_trap.o \
	$(BUILD)/native/libanx/anx_native.o

NATIVE_MEDIUM_BASE_LIB_OBJS := \
	$(BUILD)/native/medium/null_data.o \
	$(BUILD)/native/medium/libanx/anx_trap.o \
	$(BUILD)/native/medium/libanx/anx_native.o

SERVER_BASE_LIB_OBJS := \
	$(BUILD)/native/server/null_data.o \
	$(BUILD)/native/server/libanx/anx_trap.o \
	$(BUILD)/native/server/libanx/anx_native.o \
	$(BUILD)/native/servers/common/server_common.o

FSYS_SERVER_BASE_LIB_OBJS := \
	$(BUILD)/native/server/null_data.o \
	$(BUILD)/native/server/libanx/anx_trap.o \
	$(BUILD)/native/server/libanx/anx_native.o \
	$(BUILD)/native/servers/common/server_common.o

FSYS_TRACE_COM2 ?= 0

ifeq ($(SERVER_TRACE_ENABLED),1)
SERVER_BASE_LIB_OBJS += \
	$(BUILD)/native/servers/common/server_trace.o
ifeq ($(FSYS_TRACE_COM2),1)
FSYS_SERVER_BASE_LIB_OBJS += \
	$(BUILD)/native/servers/common/server_trace.o
else
FSYS_SERVER_BASE_LIB_OBJS += \
	$(BUILD)/native/servers/common/server_trace_nocom2.o
endif
endif

LIBC_BUILD := $(abspath $(BUILD)/libc-$(USERLAND_MEMMODEL))
LIBC_A := $(LIBC_BUILD)/libc.a
LIBC_CRT0 := $(LIBC_BUILD)/crt0.o

BEARSSL_ROOT := lib/bearssl
BEARSSL_ABS_ROOT := $(abspath $(BEARSSL_ROOT))
BEARSSL_BUILD := $(abspath $(BUILD)/native/bearssl)
BEARSSL_A := $(BUILD)/native/libbearssl-antler.a
BEARSSL_SRCS := $(shell find $(BEARSSL_ROOT)/src $(BEARSSL_ROOT)/inc $(BEARSSL_ROOT)/antler -type f | sort)
BEARSSL_CPPFLAGS := -nostdinc -I. -I$(BEARSSL_ABS_ROOT)/antler/include
BEARSSL_CPPFLAGS += -I$(BEARSSL_ABS_ROOT)/inc -I$(BEARSSL_ABS_ROOT)/src
BEARSSL_CPPFLAGS += -Ilibc/include -Ilibc
BEARSSL_CPPFLAGS += -I.. -I../kern -I../kern/system -I../kern/system/service
BEARSSL_CPPFLAGS += -isystem $(GCC_INCLUDE_DIR)
BEARSSL_CPPFLAGS += $(filter -D%,$(CPPFLAGS))
BEARSSL_CPPFLAGS += -DBR_64=0 -DBR_SLOW_MUL=1 -DBR_SLOW_MUL15=1
BEARSSL_CPPFLAGS += -DBR_USE_URANDOM=0 -DBR_USE_UNIX_TIME=0
BEARSSL_CFLAGS := $(BEARSSL_CPPFLAGS) -std=c99 -W -Wall -Os
BEARSSL_CFLAGS += -ffreestanding -fno-builtin -fno-pic -fno-stack-protector
BEARSSL_CFLAGS += -fno-jump-tables -ffunction-sections -fdata-sections
BEARSSL_CFLAGS += -march=i8086 -mtune=i8086 -mno-protected-mode
BEARSSL_CFLAGS += -msegelf -mcmodel=medium
NATIVE_MEDIUM_CFLAGS := $(filter-out -DANTLER_NATIVE_MEMMODEL_NAME=% -DANTLER_NATIVE_MEMMODEL_CODE=%,$(BEARSSL_CFLAGS))
NATIVE_MEDIUM_CFLAGS += -DANTLER_NATIVE_MEMMODEL_NAME=\"medium\"
NATIVE_MEDIUM_CFLAGS += -DANTLER_NATIVE_MEMMODEL_CODE=\"M\"

# Imported ELKS command packages.  Keep generic user tools here; Antler-only
# kernel management tools are built from userland/apps below.
ELKS_APP_ROOT := apps/elkscmd

ELKS_REAL_COMMANDS := \
	awk banner basename beep cal cat chgrp chmod chown clear cmp cp cron crontab cut \
	date dd decomp16 df diff dirname du e2fsck ecalc echo ed antler_compat env false fgrep file \
	find getty grep groupadd hd head kilo l ln login logname ls mail \
	man mesg miniterm mkdir mkfifo mkfs.ext2 mknod more mv nice \
	od park partype passwd posix-ipc-smoke printenv proto pwdauth pwd ramdisk rdev \
	remsync rm rmdir sed sercat shutdown sleep sort split stty sum sync \
	tail tar tee test tget time touch tr true tty uname uniq uudecode \
	useradd uuencode wc which who whoami write xargs yes

ELKS_REAL_BINS := $(foreach cmd,$(ELKS_REAL_COMMANDS),$(BUILD)/bin/$(cmd))
ELKS_REAL_BINS += $(BUILD)/bin/vi $(BUILD)/bin/sh

ELKS_REAL_SRC_banner := $(ELKS_APP_ROOT)/minix1/banner.c
ELKS_REAL_SRC_awk := apps/antler/awk/awk.c
ELKS_REAL_SRC_basename := $(ELKS_APP_ROOT)/sh_utils/basename.c
ELKS_REAL_SRC_beep := $(ELKS_APP_ROOT)/sys_utils/beep.c
ELKS_REAL_SRC_cal := $(ELKS_APP_ROOT)/minix3/cal.c
ELKS_REAL_SRC_cat := $(ELKS_APP_ROOT)/file_utils/cat.c
ELKS_REAL_SRC_chgrp := $(ELKS_APP_ROOT)/file_utils/chgrp.c
ELKS_REAL_SRC_chmod := $(ELKS_APP_ROOT)/file_utils/chmod.c
ELKS_REAL_SRC_chown := $(ELKS_APP_ROOT)/file_utils/chown.c
ELKS_REAL_SRC_cksum := $(ELKS_APP_ROOT)/minix1/cksum.c
ELKS_REAL_SRC_clear := $(ELKS_APP_ROOT)/sh_utils/clear.c
ELKS_REAL_SRC_cmp := $(ELKS_APP_ROOT)/file_utils/cmp.c
ELKS_REAL_SRC_compress := $(ELKS_APP_ROOT)/misc_utils/compress.c
ELKS_REAL_SRC_cp := $(ELKS_APP_ROOT)/file_utils/cp.c
ELKS_REAL_SRC_cron := apps/antler/cron/cron.c
ELKS_REAL_SRC_crontab := apps/antler/cron/crontab.c
ELKS_REAL_SRC_cut := $(ELKS_APP_ROOT)/minix1/cut.c
ELKS_REAL_SRC_date := $(ELKS_APP_ROOT)/sh_utils/date.c
ELKS_REAL_SRC_dd := $(ELKS_APP_ROOT)/file_utils/dd.c
ELKS_REAL_SRC_decomp16 := $(ELKS_APP_ROOT)/minix1/decomp16.c
ELKS_REAL_SRC_df := $(ELKS_APP_ROOT)/disk_utils/df.c
ELKS_REAL_SRC_diff := $(ELKS_APP_ROOT)/minix3/diff.c
ELKS_REAL_SRC_dirname := $(ELKS_APP_ROOT)/sh_utils/dirname.c
ELKS_REAL_SRC_du := $(ELKS_APP_ROOT)/minix1/du.c
ELKS_REAL_SRC_e2fsck := $(ELKS_APP_ROOT)/disk_utils/e2fsck.c
ELKS_REAL_SRC_ecalc := $(ELKS_APP_ROOT)/misc_utils/ecalc.c
ELKS_REAL_SRC_echo := $(ELKS_APP_ROOT)/sh_utils/echo.c
ELKS_REAL_SRC_ed := $(ELKS_APP_ROOT)/misc_utils/ed.c
ELKS_REAL_SRC_antler_compat := $(ELKS_APP_ROOT)/sys_utils/elks_compat.c
ELKS_REAL_SRC_env := $(ELKS_APP_ROOT)/minix2/env.c
ELKS_REAL_SRC_false := $(ELKS_APP_ROOT)/sh_utils/false.c
ELKS_REAL_SRC_fdisk := $(ELKS_APP_ROOT)/disk_utils/fdisk.c
ELKS_REAL_SRC_fgrep := $(ELKS_APP_ROOT)/minix1/fgrep.c
ELKS_REAL_SRC_file := $(ELKS_APP_ROOT)/minix3/file.c
ELKS_REAL_SRC_find := $(ELKS_APP_ROOT)/minix3/find.c
ELKS_REAL_SRC_fsck := $(ELKS_APP_ROOT)/disk_utils/fsck.c
ELKS_REAL_SRC_getty := $(ELKS_APP_ROOT)/sys_utils/getty.c
ELKS_REAL_SRC_grep := $(ELKS_APP_ROOT)/file_utils/grep.c
ELKS_REAL_SRC_groupadd := apps/antler/account/accountctl.c
ELKS_REAL_SRC_hd := $(ELKS_APP_ROOT)/misc_utils/hd.c
ELKS_REAL_SRC_head := $(ELKS_APP_ROOT)/minix3/head.c
ELKS_REAL_SRC_kilo := $(ELKS_APP_ROOT)/misc_utils/kilo.c
ELKS_REAL_SRC_l := $(ELKS_APP_ROOT)/file_utils/l.c
ELKS_REAL_SRC_ln := $(ELKS_APP_ROOT)/file_utils/ln.c
ELKS_REAL_SRC_login := $(ELKS_APP_ROOT)/sys_utils/login.c
ELKS_REAL_SRC_logname := $(ELKS_APP_ROOT)/sh_utils/logname.c
ELKS_REAL_SRC_ls := $(ELKS_APP_ROOT)/file_utils/ls.c
ELKS_REAL_SRC_mail := $(ELKS_APP_ROOT)/minix3/mail.c
ELKS_REAL_SRC_man := $(ELKS_APP_ROOT)/sys_utils/man.c
ELKS_REAL_SRC_md5sum := $(ELKS_APP_ROOT)/file_utils/md5sum.c
ELKS_REAL_SRC_mesg := $(ELKS_APP_ROOT)/sh_utils/mesg.c
ELKS_REAL_SRC_miniterm := $(ELKS_APP_ROOT)/misc_utils/miniterm.c
ELKS_REAL_SRC_mkdir := $(ELKS_APP_ROOT)/file_utils/mkdir.c
ELKS_REAL_SRC_mkfifo := $(ELKS_APP_ROOT)/file_utils/mkfifo.c
ELKS_REAL_SRC_mkfs := $(ELKS_APP_ROOT)/disk_utils/mkfs.c
ELKS_REAL_SRC_mkfs.ext2 := $(ELKS_APP_ROOT)/disk_utils/mkfs_ext2.c
ELKS_REAL_SRC_mknod := $(ELKS_APP_ROOT)/file_utils/mknod.c
ELKS_REAL_SRC_more := $(ELKS_APP_ROOT)/file_utils/more.c
ELKS_REAL_SRC_mv := $(ELKS_APP_ROOT)/file_utils/mv.c
ELKS_REAL_SRC_nice := apps/antler/nice/nice.c
ELKS_REAL_SRC_od := $(ELKS_APP_ROOT)/misc_utils/od.c
ELKS_REAL_SRC_park := $(ELKS_APP_ROOT)/disk_utils/park.c
ELKS_REAL_SRC_partype := $(ELKS_APP_ROOT)/disk_utils/partype.c
ELKS_REAL_SRC_passwd := $(ELKS_APP_ROOT)/sys_utils/passwd.c
ELKS_REAL_SRC_posix-ipc-smoke := $(ELKS_APP_ROOT)/sys_utils/posix-ipc-smoke.c
ELKS_REAL_SRC_printenv := $(ELKS_APP_ROOT)/sh_utils/printenv.c
ELKS_REAL_SRC_proto := $(ELKS_APP_ROOT)/minix1/proto.c
ELKS_REAL_SRC_pwdauth := $(ELKS_APP_ROOT)/minix2/pwdauth.c
ELKS_REAL_SRC_pwd := $(ELKS_APP_ROOT)/sh_utils/pwd.c
ELKS_REAL_SRC_ramdisk := $(ELKS_APP_ROOT)/disk_utils/ramdisk.c
ELKS_REAL_SRC_rdev := $(ELKS_APP_ROOT)/sys_utils/rdev.c
ELKS_REAL_SRC_remsync := $(ELKS_APP_ROOT)/minix2/remsync.c
ELKS_REAL_SRC_rm := $(ELKS_APP_ROOT)/file_utils/rm.c
ELKS_REAL_SRC_rmdir := $(ELKS_APP_ROOT)/file_utils/rmdir.c
ELKS_REAL_SRC_sed := $(ELKS_APP_ROOT)/minix3/sed.c
ELKS_REAL_SRC_sercat := $(ELKS_APP_ROOT)/sys_utils/sercat.c
ELKS_REAL_SRC_shutdown := $(ELKS_APP_ROOT)/sys_utils/shutdown.c
ELKS_REAL_SRC_sleep := $(ELKS_APP_ROOT)/misc_utils/sleep.c
ELKS_REAL_SRC_sort := $(ELKS_APP_ROOT)/minix3/sort.c
ELKS_REAL_SRC_split := $(ELKS_APP_ROOT)/file_utils/split.c
ELKS_REAL_SRC_stty := $(ELKS_APP_ROOT)/sh_utils/stty.c
ELKS_REAL_SRC_sum := $(ELKS_APP_ROOT)/minix1/sum.c
ELKS_REAL_SRC_sync := $(ELKS_APP_ROOT)/file_utils/sync.c
ELKS_REAL_SRC_synctree := $(ELKS_APP_ROOT)/minix2/synctree.c
ELKS_REAL_SRC_sysctl := $(ELKS_APP_ROOT)/sys_utils/sysctl.c
ELKS_REAL_SRC_tail := $(ELKS_APP_ROOT)/minix3/tail.c
ELKS_REAL_SRC_tar := $(ELKS_APP_ROOT)/misc_utils/tar.c
ELKS_REAL_SRC_tee := $(ELKS_APP_ROOT)/minix3/tee.c
ELKS_REAL_SRC_test := $(ELKS_APP_ROOT)/sh_utils/test.c
ELKS_REAL_SRC_tget := $(ELKS_APP_ROOT)/minix2/tget.c
ELKS_REAL_SRC_time := $(ELKS_APP_ROOT)/misc_utils/time.c
ELKS_REAL_SRC_touch := $(ELKS_APP_ROOT)/file_utils/touch.c
ELKS_REAL_SRC_tr := $(ELKS_APP_ROOT)/sh_utils/tr.c
ELKS_REAL_SRC_true := $(ELKS_APP_ROOT)/sh_utils/true.c
ELKS_REAL_SRC_tty := $(ELKS_APP_ROOT)/misc_utils/tty.c
ELKS_REAL_SRC_uname := $(ELKS_APP_ROOT)/sh_utils/uname.c
ELKS_REAL_SRC_uniq := $(ELKS_APP_ROOT)/minix1/uniq.c
ELKS_REAL_SRC_useradd := apps/antler/account/accountctl.c
ELKS_REAL_SRC_uudecode := $(ELKS_APP_ROOT)/misc_utils/uudecode.c
ELKS_REAL_SRC_uuencode := $(ELKS_APP_ROOT)/misc_utils/uuencode.c
ELKS_REAL_SRC_wc := $(ELKS_APP_ROOT)/minix1/wc.c
ELKS_REAL_SRC_which := $(ELKS_APP_ROOT)/sh_utils/which.c
ELKS_REAL_SRC_who := $(ELKS_APP_ROOT)/sys_utils/who.c
ELKS_REAL_SRC_whoami := $(ELKS_APP_ROOT)/sh_utils/whoami.c
ELKS_REAL_SRC_write := $(ELKS_APP_ROOT)/sh_utils/write.c
ELKS_REAL_SRC_xargs := $(ELKS_APP_ROOT)/sh_utils/xargs.c
ELKS_REAL_SRC_yes := $(ELKS_APP_ROOT)/sh_utils/yes.c

ELKS_REAL_ARCHIVE_ARGS := \
	$(foreach cmd,$(ELKS_REAL_COMMANDS),bin/$(cmd)=$(BUILD)/bin/$(cmd)) \
	bin/[=$(BUILD)/bin/test \
	bin/ash=$(BUILD)/bin/sh \
	bin/elvis=$(BUILD)/bin/vi \
	bin/ex=$(BUILD)/bin/vi \
	bin/view=$(BUILD)/bin/vi

ELKS_REAL_CFLAGS := -Ilibc/include -Ilibc $(CFLAGS)
ELKS_REAL_CFLAGS += -I$(ELKS_APP_ROOT) -I$(ELKS_APP_ROOT)/sh_utils
ELKS_REAL_CFLAGS += -I$(ELKS_APP_ROOT)/file_utils -I$(ELKS_APP_ROOT)/misc_utils
ELKS_REAL_CFLAGS += -I$(ELKS_APP_ROOT)/disk_utils -I$(ELKS_APP_ROOT)/sys_utils
ELKS_REAL_CFLAGS += -I$(ELKS_APP_ROOT)/minix1
ELKS_REAL_CFLAGS += -I$(ELKS_APP_ROOT)/minix2 -I$(ELKS_APP_ROOT)/minix3
ELKS_REAL_CFLAGS += -D__HAS_NO_FLOATS__
ELKS_REAL_CFLAGS_antler_compat := -DEC_ELKS_MEMINFO=1 \
	-I$(SERVER_SRC_ROOT)/fsys/service

ELKS_ASH_OBJS := \
	builtins.o cd.o dirent.o error.o eval.o exec.o expand.o input.o \
	jobs.o mail.o main.o memalloc.o miscbltin.o mystring.o nodes.o \
	options.o parser.o redir.o show.o signames.o syntax.o trap.o \
	output.o var.o init.o bltin/echo.o bltin/expr.o bltin/regexp.o \
	bltin/operators.o
ELKS_ASH_OBJ_PATHS := \
	$(addprefix $(BUILD)/native/elks/ash/,$(ELKS_ASH_OBJS))
ELKS_ASH_CFLAGS := $(ELKS_REAL_CFLAGS) -I$(ELKS_APP_ROOT)/ash \
	-DSHELL -D_MINIX -D_POSIX_SOURCE -Dlint -Wno-implicit-int
ELKS_ASH_CFLAGS += -DANX_ASH_SPAWN_TRACE=$(ASH_SPAWN_TRACE)
# Keep the complete interactive/job-control shell below one 8086 code segment.
# GCC's called-once and small-function inlining expands this old K&R source
# enough to cross the ANTX 64 KiB text boundary without improving XT latency.
ELKS_ASH_CFLAGS += -fno-inline-functions-called-once -fno-inline-small-functions

ELKS_SASH_OBJS := \
	sash.o cmds.o cmd_dd.o cmd_ed.o cmd_grep.o cmd_ls.o cmd_tar.o \
	utils.o cmd_history.o
ELKS_SASH_OBJ_PATHS := \
	$(addprefix $(BUILD)/native/elks/sash/,$(ELKS_SASH_OBJS))
ELKS_SASH_CFLAGS := $(ELKS_REAL_CFLAGS) -I$(ELKS_APP_ROOT)/sash \
	-Wno-implicit-int

ELKS_ELVIS_OBJS := \
	blk.o cmd1.o cmd2.o curses.o cut.o ex.o input.o main.o misc.o \
	modify.o move1.o move2.o move3.o move4.o move5.o opts.o recycle.o \
	redraw.o regexp.o regsub.o system.o tinytcap.o tio.o tmp.o vars.o \
	vcmd.o vi.o
ELKS_ELVIS_OBJ_PATHS := \
	$(addprefix $(BUILD)/native/elks/elvis/,$(ELKS_ELVIS_OBJS))
ELKS_ELVIS_CFLAGS := $(ELKS_REAL_CFLAGS) -I$(ELKS_APP_ROOT)/elvis \
	-DM_SYSV -DCRUNCH -DNO_MKEXRC -DNO_CURSORSHAPE -DNO_CHARATTR \
	-DNO_SHOWMODE -DNO_MODELINE -DNO_OPTCOLS -DNO_DIGRAPH -DNO_ABBR \
	-DNO_AT -DNO_SENTENCE -DNO_ERRLIST -DNO_EXTENSIONS -DNO_RECYCLE \
	-DNO_MAGIC -DNO_CHARSEARCH -DNO_NONEX -DNO_SHOWMATCH -DNO_VERSION \
	-DBLKSIZE=512 -DKBSIZ=2048 -DMAXMAPS=16

NATIVE_DIAG_COMMANDS := \
	id mfmregs hostname

NATIVE_DRIVER_COMMANDS := \
	insmod rmmod load-driver unload-driver

NATIVE_NETWORK_COMMANDS := \
	net netpoll \
	arp ftpd httpd ifconfig mii-tool nameif netcat netstat \
	ntpdate plipconfig rarp route slattach

NATIVE_DIRECT_COMMANDS := $(NATIVE_DIAG_COMMANDS) $(NATIVE_DRIVER_COMMANDS)

ifneq ($(filter 1 yes,$(ENABLE_DIRECTFD_DRIVER)),)
NATIVE_DIRECT_COMMANDS += fdc-smoke fdcstat
endif

ifneq ($(filter 1 yes,$(ENABLE_GAMEPORT_DRIVER)),)
NATIVE_DIRECT_COMMANDS += gameportctl
endif

ifeq ($(ENABLE_RAMDISK_DRIVER),1)
NATIVE_DIRECT_COMMANDS += ramdisk-smoke
endif

ifeq ($(ENABLE_NETWORK),1)
NATIVE_DIRECT_COMMANDS += $(NATIVE_NETWORK_COMMANDS)
endif

ifneq ($(filter 1 yes,$(ENABLE_SOUND) $(SOUND_SERVICE_ENABLE) $(START_SOUND_ON_BOOT) $(ESD_ENABLE)),)
NATIVE_DIRECT_COMMANDS += esd oss_beep ossinfo pcmplay
endif

NATIVE_DIRECT_BINS := \
	$(foreach cmd,$(NATIVE_DIRECT_COMMANDS),$(BUILD)/bin/$(cmd))

NATIVE_DIRECT_EXTRA_OBJS_netpoll := \
	$(if $(filter 1,$(SERVER_TRACE_ENABLED)),$(BUILD)/native/servers/common/server_trace.o,)

NATIVE_DIRECT_EXTRA_OBJS_net := \
	$(if $(filter 1,$(SERVER_TRACE_ENABLED)),$(BUILD)/native/servers/common/server_trace.o,)

NFS_SERVER_OBJS := \
	$(BUILD)/native/servers/nfs/service/main.o \
	$(BUILD)/native/servers/nfs/core/dispatch.o \
	$(BUILD)/native/servers/nfs/core/nfs.o \
	$(BUILD)/native/servers/nfs/core/nfsrpc.o \
	$(BUILD)/native/servers/nfs/core/support.o

EXT2_CORE_OBJS := \
	$(BUILD)/native/servers/filesystem/core/ext2/runtime.o \
	$(BUILD)/native/servers/filesystem/core/ext2/debug.o \
	$(BUILD)/native/servers/filesystem/core/ext2/super.o \
	$(BUILD)/native/servers/filesystem/core/ext2/allocation.o \
	$(BUILD)/native/servers/filesystem/core/ext2/directory.o \
	$(BUILD)/native/servers/filesystem/core/ext2/file_io.o \
	$(BUILD)/native/servers/filesystem/core/ext2/mutation.o

EXT2_INTERNAL_HEADERS := \
	$(wildcard $(SERVER_SRC_ROOT)/filesystem/core/ext2/*.h)

EXT2FS_SERVICE_OBJS := \
	$(BUILD)/native/servers/ext2fs/service/main.o \
	$(BUILD)/native/servers/ext2fs/service/resize.o \
	$(EXT2_CORE_OBJS)

FATFS_SERVICE_OBJS := \
	$(BUILD)/native/servers/fatfs/service/main.o

FSYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/fsys/service/main.o \
	$(BUILD)/native/servers/fsys/core/runtime.o \
	$(BUILD)/native/servers/fsys/core/state.o \
	$(BUILD)/native/servers/fsys/backend/device.o \
	$(BUILD)/native/servers/fsys/backend/mount.o \
	$(BUILD)/native/servers/fsys/backend/root_block.o \
	$(BUILD)/native/servers/fsys/backend/ext2.o \
	$(BUILD)/native/servers/fsys/backend/nfs.o \
	$(BUILD)/native/servers/fsys/backend/fat.o \
	$(BUILD)/native/servers/fsys/node/node.o \
	$(BUILD)/native/servers/fsys/fd/table.o \
	$(BUILD)/native/servers/fsys/fd/io.o \
	$(BUILD)/native/servers/fsys/fd/exec.o \
	$(BUILD)/native/servers/fsys/fd/exec_image.o \
	$(BUILD)/native/servers/fsys/fd/truncate.o \
	$(BUILD)/native/servers/fsys/fd/block.o \
	$(BUILD)/native/servers/fsys/fd/gameport.o \
	$(BUILD)/native/servers/fsys/ipc/pipe.o \
	$(BUILD)/native/servers/fsys/ipc/posix.o \
	$(BUILD)/native/servers/fsys/pty/pty.o \
	$(BUILD)/native/servers/fsys/proc/proc.o \
	$(BUILD)/native/servers/fsys/path/path.o \
	$(BUILD)/native/servers/filesystem/core/vfs.o \
	$(BUILD)/native/servers/storage/core/bio.o

FSYS_INTERNAL_HEADERS := \
	$(SERVER_SRC_ROOT)/fsys/core/fsys_internal.h \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/core/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/backend/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/node/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/fd/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/ipc/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/pty/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/proc/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/path/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/fsys/service/*.h)

SERSYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/sersys/service/main.o \
	$(BUILD)/native/servers/sersys/service/pointer_lease.o \
	$(BUILD)/native/servers/drivers/serial/uart8250.o \
	$(BUILD)/native/servers/drivers/serial/uart16450.o \
	$(BUILD)/native/servers/tty/core/tty_core.o

KEYSYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/keysys/service/main.o \
	$(BUILD)/native/servers/keysys/input/set1_decoder.o \
	$(BUILD)/native/servers/keysys/pointer/pointer_link.o

POINTERSYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/pointersys/service/main.o \
	$(BUILD)/native/servers/pointersys/core/event_ring.o \
	$(BUILD)/native/servers/drivers/input/amstrad.o \
	$(BUILD)/native/servers/pointersys/driver/sersys_raw.o \
	$(BUILD)/native/servers/pointersys/protocol/microsoft.o \
	$(BUILD)/native/servers/drivers/core/portio.o

IPSERIAL_SERVICE_OBJS := \
	$(BUILD)/native/servers/ipserial/service/main.o \
	$(BUILD)/native/servers/tty/core/tty_core.o

NETSYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/netsys/service/main.o

NATIVESYS_SERVICE_OBJS := \
	$(BUILD)/native/servers/nativesys/service/main.o

ifeq ($(ENABLE_NETWORK),1)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/core/driver_log.o \
	$(BUILD)/native/servers/drivers/core/portio.o \
	$(BUILD)/native/servers/network_stack/link/arp.o \
	$(BUILD)/native/servers/network_stack/config/dns.o \
	$(BUILD)/native/servers/network_stack/link/driver.o \
	$(BUILD)/native/servers/network_stack/link/eth.o \
	$(BUILD)/native/servers/network_stack/ip/ip.o \
	$(BUILD)/native/servers/network_stack/transport/sock.o \
	$(BUILD)/native/servers/network_stack/core/stack.o \
	$(BUILD)/native/servers/network_stack/transport/tcp.o \
	$(BUILD)/native/servers/network_stack/transport/udp.o
ifeq ($(NET_DRIVER),ne2k)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/net/ne2k.o
else ifeq ($(NET_DRIVER),wd80x3)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/net/wd80x3.o
else ifeq ($(NET_DRIVER),el3)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/net/el3.o
else ifeq ($(NET_DRIVER),83c790qf)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/net/dp83c790.o
else ifeq ($(NET_DRIVER),ultra)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/net/dp83c790.o
endif
else
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/network_stack/link/null.o
endif

ifeq ($(ENABLE_DHCP_CLIENT),1)
NETSYS_SERVICE_OBJS += \
	$(BUILD)/native/servers/network_stack/config/dhcp.o
endif

DRIVERD_SERVICE_OBJS := \
	$(BUILD)/native/servers/driverd/service/main.o \
	$(BUILD)/native/servers/driverd/core/support.o \
	$(BUILD)/native/servers/driverd/irq/relay.o \
	$(BUILD)/native/servers/driverd/sound/device.o \
	$(BUILD)/native/servers/driverd/block/mfm.o \
	$(BUILD)/native/servers/driverd/block/ata.o \
	$(BUILD)/native/servers/driverd/block/fdc.o \
	$(BUILD)/native/servers/driverd/input/gameport.o \
	$(BUILD)/native/servers/driverd/auth/access.o \
	$(BUILD)/native/servers/drivers/core/portio.o \
	$(BUILD)/native/servers/drivers/core/isa.o \
	$(BUILD)/native/servers/drivers/core/dma.o

ifneq ($(filter 1 yes,$(ENABLE_ATA_DRIVER)),)
DRIVERD_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/block/ata.o
endif

# bios13 reuses driverd/block/ata.o's transfer staging but binds the firmware
# INT 13h mechanism instead of XTIDE PIO.
ifneq ($(filter 1 yes,$(ENABLE_BIOS13_DRIVER)),)
DRIVERD_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/block/bios13.o
endif

ifneq ($(filter 1 yes,$(ENABLE_DIRECTFD_DRIVER)),)
DRIVERD_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/block/fdc765.o
endif

ifneq ($(filter 1 yes,$(ENABLE_GAMEPORT_DRIVER)),)
DRIVERD_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/input/gameport201.o
endif

DRIVERD_INTERNAL_HEADERS := \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/service/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/core/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/irq/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/sound/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/block/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/input/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/driverd/auth/*.h)

ifneq ($(filter 1 yes,$(ENABLE_MFM_DRIVER)),)
DRIVERD_SERVICE_OBJS += \
	$(BUILD)/native/servers/drivers/core/driver_log.o \
	$(BUILD)/native/servers/drivers/block/mfm.o \
	$(BUILD)/native/servers/storage/core/bio.o
endif

NATIVE_BINS := \
	$(BUILD)/bin/fsys \
	$(BUILD)/bin/ext2fs \
	$(BUILD)/bin/fatfs \
	$(BUILD)/bin/nativesys \
	$(BUILD)/bin/sersys \
	$(BUILD)/bin/keysys \
	$(BUILD)/bin/pointersys \
	$(BUILD)/bin/driverd \
	$(BUILD)/bin/antler-init \
	$(BUILD)/bin/service \
	$(BUILD)/bin/modprobe \
	$(BUILD)/bin/dmesg \
	$(BUILD)/bin/segmap \
	$(BUILD)/bin/mount \
	$(BUILD)/bin/umount \
	$(BUILD)/bin/anx2ctl \
	$(NATIVE_DIRECT_BINS) \
	$(ELKS_REAL_BINS)

ifeq ($(ENABLE_NETWORK),1)
NATIVE_BINS += $(BUILD)/bin/netsys
endif

# Keep these zero-data-cost hard-link aliases synchronized with the anx2ctl
# entries in root/etc/anx2/commands.  Only commands with a real direct handler
# belong here: publishing legacy ANX2 names which nativesys rejects would turn
# a clear "not found" into a misleading executable that always fails ENODEV.
ANX2_SERVICE_COMMANDS := \
	abi contract dev device free kernel kernelctl lsmod meminfo memory modinfo \
	netmap network ps sin slay sys sysctl top tsk

NATIVE_ARCHIVE_ARGS := \
	system/servers/fsys=$(BUILD)/bin/fsys \
	system/servers/ext2fs=$(BUILD)/bin/ext2fs \
	system/servers/fatfs=$(BUILD)/bin/fatfs \
	system/servers/nativesys=$(BUILD)/bin/nativesys \
	system/servers/sersys=$(BUILD)/bin/sersys \
	system/servers/keysys=$(BUILD)/bin/keysys \
	system/servers/pointersys=$(BUILD)/bin/pointersys \
	system/servers/driverd=$(BUILD)/bin/driverd \
	bin/sh=$(BUILD)/bin/sh \
	bin/mount=$(BUILD)/bin/mount \
	bin/umount=$(BUILD)/bin/umount \
	bin/service=$(BUILD)/bin/service \
	bin/modprobe=$(BUILD)/bin/modprobe \
	bin/dmesg=$(BUILD)/bin/dmesg \
	bin/segmap=$(BUILD)/bin/segmap \
	bin/anx2ctl=$(BUILD)/bin/anx2ctl \
	$(foreach cmd,$(NATIVE_DIRECT_COMMANDS),bin/$(cmd)=$(BUILD)/bin/$(cmd)) \
	$(ELKS_REAL_ARCHIVE_ARGS)

ifeq ($(ENABLE_NETWORK),1)
NATIVE_ARCHIVE_ARGS += \
	system/servers/netsys=$(BUILD)/bin/netsys \
	system/servers/netpoll=$(BUILD)/bin/netpoll
# The BearSSL HTTPS fetch helper is a medium-model program and only makes
# sense with the network stack present, so it is gated on both switches.
ifneq ($(filter 1 yes,$(ENABLE_HTTPS)),)
NATIVE_BINS += $(BUILD)/bin/https
NATIVE_ARCHIVE_ARGS += bin/https=$(BUILD)/bin/https
endif
endif

ifneq ($(filter 1 yes,$(IPSERIAL_ENABLE)),)
NATIVE_BINS += $(BUILD)/bin/ipserial
NATIVE_ARCHIVE_ARGS += system/servers/ipserial=$(BUILD)/bin/ipserial
endif

ifneq ($(filter 1 yes,$(ENABLE_NFS)),)
NATIVE_BINS += $(BUILD)/bin/nfs
NATIVE_ARCHIVE_ARGS += \
	system/servers/nfs=$(BUILD)/bin/nfs
endif

ifneq ($(filter 1 yes,$(ENABLE_SOUND) $(SOUND_SERVICE_ENABLE) $(START_SOUND_ON_BOOT) $(ESD_ENABLE)),)
NATIVE_ARCHIVE_ARGS += \
	bin/pcmplay=$(BUILD)/bin/pcmplay
endif

ifeq ($(ENABLE_RAMDISK_DRIVER),1)
NATIVE_BINS += $(BUILD)/bin/ramdiskd
NATIVE_ARCHIVE_ARGS += system/servers/ramdisk=$(BUILD)/bin/ramdiskd
endif

# Antler uses independent native VDI and AES services plus trap-linked GEM
# applications.
include gem/Antler.mk
include gem/mk/host-tests.mk

ANX2_SERVICE_ARCHIVE_ARGS := \
	$(foreach cmd,$(ANX2_SERVICE_COMMANDS),bin/$(cmd)=$(BUILD)/bin/anx2ctl)


USERLAND_PUBLIC_HEADERS := \
	$(wildcard $(PROJECT_ROOT)/arch/i8086/*.h) \
	$(wildcard ../kern/nucleus/*.h) \
	$(wildcard ../kern/nucleus/*/*.h) \
	$(wildcard ../kern/system/*.h) \
	$(wildcard ../kern/system/*/*.h) \
	$(wildcard ../kern/system/memory/*.h) \
	$(wildcard ../kern/system/memory/*/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/*/*.h) \
	$(wildcard $(SERVER_SRC_ROOT)/*/*/*.h) \
	$(wildcard libc/include/*.h) \
	$(wildcard libc/include/antler/*.h) \
	$(wildcard libc/include/arch/*.h) \
	$(wildcard libc/include/arpa/*.h) \
	$(wildcard libc/include/netinet/*.h) \
	$(wildcard libc/include/sys/*.h)

.PHONY: all native archive full-native full-archive rootfs-debugfs-script \
	clean FORCE check-toolchain

FORCE:

check-toolchain:
	@if ! command -v "$(CC)" >/dev/null 2>&1; then \
		echo "missing IA-16 compiler: $(CC)" >&2; \
		echo "install toolchain/gcc-ia16 to $(TOOLCHAIN_DIR)/cross, or set CROSS=/path/to/ia16-elf-" >&2; \
		exit 1; \
	fi
	@if ! command -v "$(LD)" >/dev/null 2>&1 \
		|| ! command -v "$(OBJCOPY)" >/dev/null 2>&1 \
		|| ! command -v "$(OBJDUMP)" >/dev/null 2>&1; then \
		echo "missing IA-16 binutils under CROSS=$(CROSS)" >&2; \
		exit 1; \
	fi

$(BUILD_CONFIG): FORCE check-toolchain
	@mkdir -p $(dir $@)
	@{ \
			printf '%s\n' 'CC=$(CC)'; \
			printf '%s\n' 'LD=$(LD)'; \
			printf '%s\n' 'LDFLAGS=$(LDFLAGS)'; \
			printf '%s\n' 'CPPFLAGS=$(CPPFLAGS)'; \
			printf '%s\n' 'CFLAGS=$(CFLAGS)'; \
			printf '%s\n' 'SERVER_CFLAGS=$(SERVER_CFLAGS)'; \
			printf '%s\n' 'USERLAND_MEMMODEL=$(USERLAND_MEMMODEL)'; \
			printf '%s\n' 'USERLAND_SERVER_MEMMODEL=$(USERLAND_SERVER_MEMMODEL)'; \
			printf '%s\n' 'MACHINE_PROFILE=$(MACHINE_PROFILE)'; \
			printf '%s\n' 'ANTLER_LPT_BASE=$(ANTLER_LPT_BASE)'; \
			printf '%s\n' 'ROOT_BLOCK_BACKEND=$(ROOT_BLOCK_BACKEND)'; \
		printf '%s\n' 'ROOT_DEVICE=$(ROOT_DEVICE)'; \
		printf '%s\n' 'ROOT_FS_TYPE=$(ROOT_FS_TYPE)'; \
			printf '%s\n' 'ROOT_FLAGS=$(ROOT_FLAGS)'; \
			printf '%s\n' 'GEM_RUNLEVEL=$(GEM_RUNLEVEL)'; \
			printf '%s\n' 'FS_ENABLE_EXT2_MOUNT_RUNTIME=$(FS_ENABLE_EXT2_MOUNT_RUNTIME)'; \
			printf '%s\n' 'SYSINIT_EXTRA_LINE=$(SYSINIT_EXTRA_LINE)'; \
			printf '%s\n' 'KERNEL_DEBUG_TTY=$(KERNEL_DEBUG_TTY)'; \
				printf '%s\n' 'SERIAL_DEBUG=$(SERIAL_DEBUG)'; \
				printf '%s\n' 'LEGACY_8250_TRACE=$(LEGACY_8250_TRACE)'; \
				printf '%s\n' 'LEGACY_8250_TRACE_BASE=$(LEGACY_8250_TRACE_BASE)'; \
				printf '%s\n' 'SERVER_TRACE_COM2=$(SERVER_TRACE_COM2)'; \
				printf '%s\n' 'SERVER_TRACE_COM2_BASE=$(SERVER_TRACE_COM2_BASE)'; \
				printf '%s\n' 'SERVER_TRACE_COM2_DIVISOR=$(SERVER_TRACE_COM2_DIVISOR)'; \
				printf '%s\n' 'SERVER_TRACE_DEBUG_PORT=$(SERVER_TRACE_DEBUG_PORT)'; \
				printf '%s\n' 'SERVER_TRACE_DEBUG_PORT_IO=$(SERVER_TRACE_DEBUG_PORT_IO)'; \
				printf '%s\n' 'SERSYS_TTYS0=$(SERSYS_TTYS0)'; \
				printf '%s\n' 'SERSYS_TTYS1=$(SERSYS_TTYS1)'; \
				printf '%s\n' 'SERSYS_TTYS2=$(SERSYS_TTYS2)'; \
				printf '%s\n' 'SERSYS_TTYS3=$(SERSYS_TTYS3)'; \
				printf '%s\n' 'SERSYS_TTYS0_BASE=$(SERSYS_TTYS0_BASE)'; \
				printf '%s\n' 'SERSYS_TTYS1_BASE=$(SERSYS_TTYS1_BASE)'; \
				printf '%s\n' 'SERSYS_TTYS2_BASE=$(SERSYS_TTYS2_BASE)'; \
				printf '%s\n' 'SERSYS_TTYS3_BASE=$(SERSYS_TTYS3_BASE)'; \
					printf '%s\n' 'SERSYS_TTYS0_TYPE=$(SERSYS_TTYS0_TYPE)'; \
					printf '%s\n' 'SERSYS_TTYS1_TYPE=$(SERSYS_TTYS1_TYPE)'; \
					printf '%s\n' 'SERSYS_TTYS2_TYPE=$(SERSYS_TTYS2_TYPE)'; \
					printf '%s\n' 'SERSYS_TTYS3_TYPE=$(SERSYS_TTYS3_TYPE)'; \
					printf '%s\n' 'SERSYS_IRQ_AWARE=$(SERSYS_IRQ_AWARE)'; \
					printf '%s\n' 'SERSYS_TTYS0_IRQ=$(SERSYS_TTYS0_IRQ)'; \
					printf '%s\n' 'SERSYS_TTYS1_IRQ=$(SERSYS_TTYS1_IRQ)'; \
					printf '%s\n' 'SERSYS_TTYS2_IRQ=$(SERSYS_TTYS2_IRQ)'; \
					printf '%s\n' 'SERSYS_TTYS3_IRQ=$(SERSYS_TTYS3_IRQ)'; \
					printf '%s\n' 'SERSYS_TTYS0_FLOW=$(SERSYS_TTYS0_FLOW)'; \
					printf '%s\n' 'SERSYS_TTYS1_FLOW=$(SERSYS_TTYS1_FLOW)'; \
					printf '%s\n' 'SERSYS_TTYS2_FLOW=$(SERSYS_TTYS2_FLOW)'; \
					printf '%s\n' 'SERSYS_TTYS3_FLOW=$(SERSYS_TTYS3_FLOW)'; \
					printf '%s\n' 'BOOT_USERLAND_DEBUG=$(BOOT_USERLAND_DEBUG)'; \
			printf '%s\n' 'GEM_VIDEO_ADAPTER=$(GEM_VIDEO_ADAPTER)'; \
			printf '%s\n' 'GEM_VIDEO_ADAPTER_ID=$(GEM_VIDEO_ADAPTER_ID)'; \
			printf '%s\n' 'GEM_PC1640_PEGA=$(GEM_PC1640_PEGA)'; \
			printf '%s\n' 'PROCESS_DEBUG=$(PROCESS_DEBUG)'; \
			printf '%s\n' 'INIT_DEBUG=$(INIT_DEBUG)'; \
			printf '%s\n' 'SERSYS_DEBUG=$(SERSYS_DEBUG)'; \
			printf '%s\n' 'DRIVER_LOG_VERBOSITY=$(DRIVER_LOG_VERBOSITY)'; \
					printf '%s\n' 'ENABLE_NETWORK=$(ENABLE_NETWORK)'; \
					printf '%s\n' 'ENABLE_HTTPS=$(ENABLE_HTTPS)'; \
					printf '%s\n' 'START_NETWORK_ON_BOOT=$(START_NETWORK_ON_BOOT)'; \
			printf '%s\n' 'START_EXT2FS_ON_BOOT=$(START_EXT2FS_ON_BOOT)'; \
			printf '%s\n' 'NFS_START_NETWORK_ON_BOOT=$(NFS_START_NETWORK_ON_BOOT)'; \
				printf '%s\n' 'ENABLE_MFM_DRIVER=$(ENABLE_MFM_DRIVER)'; \
				printf '%s\n' 'ENABLE_DIRECTFD_DRIVER=$(ENABLE_DIRECTFD_DRIVER)'; \
				printf '%s\n' 'ENABLE_GAMEPORT_DRIVER=$(ENABLE_GAMEPORT_DRIVER)'; \
				printf '%s\n' 'NET_DRIVER=$(NET_DRIVER)'; \
				printf '%s\n' 'NET_PROBE_SELF_TEST=$(NET_PROBE_SELF_TEST)'; \
				printf '%s\n' 'NET_NE2K_IO=$(NET_NE2K_IO)'; \
			printf '%s\n' 'NET_NE2K_IRQ=$(NET_NE2K_IRQ)'; \
			printf '%s\n' 'NET_NE2K_BUS=$(NET_NE2K_BUS)'; \
			printf '%s\n' 'NET_NE2K_DEBUG_TX=$(NET_NE2K_DEBUG_TX)'; \
			printf '%s\n' 'NET_PACKET_PATH=$(NET_PACKET_PATH)'; \
			printf '%s\n' 'NET_COM2_TRACE=$(NET_COM2_TRACE)'; \
			printf '%s\n' 'NET_WD80X3_IO=$(NET_WD80X3_IO)'; \
			printf '%s\n' 'NET_WD80X3_IRQ=$(NET_WD80X3_IRQ)'; \
			printf '%s\n' 'NET_WD80X3_RAM=$(NET_WD80X3_RAM)'; \
			printf '%s\n' 'NET_WD80X3_FLAGS=$(NET_WD80X3_FLAGS)'; \
			printf '%s\n' 'NET_ULTRA_IO=$(NET_ULTRA_IO)'; \
				printf '%s\n' 'NET_ULTRA_IRQ=$(NET_ULTRA_IRQ)'; \
				printf '%s\n' 'NET_ULTRA_RAM=$(NET_ULTRA_RAM)'; \
				printf '%s\n' 'NET_ULTRA_FLAGS=$(NET_ULTRA_FLAGS)'; \
				printf '%s\n' 'NET_HOSTNAME=$(NET_HOSTNAME)'; \
				printf '%s\n' 'NET_IPMODE=$(NET_IPMODE)'; \
				printf '%s\n' 'NET_DHCP_ENABLE=$(NET_DHCP_ENABLE)'; \
				printf '%s\n' 'NET_DHCP_WAIT=$(NET_DHCP_WAIT)'; \
				printf '%s\n' 'NET_LOCALIP=$(NET_LOCALIP)'; \
				printf '%s\n' 'NET_GATEWAY=$(NET_GATEWAY)'; \
				printf '%s\n' 'NET_NETMASK=$(NET_NETMASK)'; \
				printf '%s\n' 'NET_DNSSERVER=$(NET_DNSSERVER)'; \
				printf '%s\n' 'NET_EXTRA_HOST_NAME=$(NET_EXTRA_HOST_NAME)'; \
				printf '%s\n' 'NET_EXTRA_HOST_IP=$(NET_EXTRA_HOST_IP)'; \
				printf '%s\n' 'NTP_ENABLE=$(NTP_ENABLE)'; \
			printf '%s\n' 'NTP_SERVER=$(NTP_SERVER)'; \
			printf '%s\n' 'NTP_TIMEOUT=$(NTP_TIMEOUT)'; \
			printf '%s\n' 'NTP_TRIES=$(NTP_TRIES)'; \
			printf '%s\n' 'NTP_LOG=$(NTP_LOG)'; \
			printf '%s\n' 'IPSERIAL_ENABLE=$(IPSERIAL_ENABLE)'; \
			printf '%s\n' 'IPSERIAL_MODE=$(IPSERIAL_MODE)'; \
			printf '%s\n' 'IPSERIAL_PORT=$(IPSERIAL_PORT)'; \
			printf '%s\n' 'ENABLE_NFS=$(ENABLE_NFS)'; \
			printf '%s\n' 'ENABLE_LOADABLE_DRIVER_MODULES=$(ENABLE_LOADABLE_DRIVER_MODULES)'; \
			printf '%s\n' 'ENABLE_DRIVER_MODULE_COMPRESSION=$(ENABLE_DRIVER_MODULE_COMPRESSION)'; \
			printf '%s\n' 'ENABLE_KERNEL_COMPRESSION=$(ENABLE_KERNEL_COMPRESSION)'; \
			printf '%s\n' 'ENABLE_SOUND=$(ENABLE_SOUND)'; \
			printf '%s\n' 'SOUND_SERVICE_ENABLE=$(SOUND_SERVICE_ENABLE)'; \
			printf '%s\n' 'START_SOUND_ON_BOOT=$(START_SOUND_ON_BOOT)'; \
			printf '%s\n' 'ESD_ENABLE=$(ESD_ENABLE)'; \
			printf '%s\n' 'DRIVERD_SOUND_ENABLE=$(DRIVERD_SOUND_ENABLE)'; \
			printf '%s\n' 'ESD_PORT=$(ESD_PORT)'; \
			printf '%s\n' 'ESD_RATE=$(ESD_RATE)'; \
			printf '%s\n' 'ESD_LOG=$(ESD_LOG)'; \
			printf '%s\n' 'SOUND_RATE=$(SOUND_RATE)'; \
			printf '%s\n' 'SB_PORT=$(SB_PORT)'; \
			printf '%s\n' 'SB_IRQ=$(SB_IRQ)'; \
			printf '%s\n' 'SB_DMA=$(SB_DMA)'; \
			printf '%s\n' 'SOUND_DRIVER=$(SOUND_DRIVER)'; \
			printf '%s\n' 'SOUND_IRQ_AWARE=$(SOUND_IRQ_AWARE)'; \
				printf '%s\n' 'MFM_ST506_IRQ=$(MFM_ST506_IRQ)'; \
				printf '%s\n' 'MFM_ST506_DMA=$(MFM_ST506_DMA)'; \
				printf '%s\n' 'MFM_IRQ_AWARE=$(MFM_IRQ_AWARE)'; \
				printf '%s\n' 'MFM_DMA_MODE=$(MFM_DMA_MODE)'; \
				printf '%s\n' 'MFM_DEBUG=$(MFM_DEBUG)'; \
				printf '%s\n' 'MFM_TRACE_SECTORS=$(MFM_TRACE_SECTORS)'; \
				printf '%s\n' 'SOUND_OPTI_SB_MODE=$(SOUND_OPTI_SB_MODE)'; \
			printf '%s\n' 'SOUND_OPTI_SB_PORT=$(SOUND_OPTI_SB_PORT)'; \
			printf '%s\n' 'SOUND_OPTI_SB_IRQ=$(SOUND_OPTI_SB_IRQ)'; \
			printf '%s\n' 'SOUND_OPTI_SB_DMA=$(SOUND_OPTI_SB_DMA)'; \
			printf '%s\n' 'NFS_SERVER=$(NFS_SERVER)'; \
			printf '%s\n' 'NFS_SERVER_IP=$(NFS_SERVER_IP)'; \
			printf '%s\n' 'NFS_EXPORT=$(NFS_EXPORT)'; \
		printf '%s\n' 'NFS_MOUNTPOINT=$(NFS_MOUNTPOINT)'; \
		printf '%s\n' 'NFS_TEST_ROOT=$(NFS_TEST_ROOT)'; \
		printf '%s\n' 'NFS_DEVICE=$(NFS_DEVICE)'; \
		printf '%s\n' 'NFS_PORT=$(NFS_PORT)'; \
		printf '%s\n' 'NFS_MOUNT_PORT=$(NFS_MOUNT_PORT)'; \
		printf '%s\n' 'NFS_TIMEOUT_TICKS=$(NFS_TIMEOUT_TICKS)'; \
		printf '%s\n' 'NFS_RETRIES=$(NFS_RETRIES)'; \
	} > $@.tmp; \
	if test -f $@ && cmp -s $@.tmp $@; then \
		rm -f $@.tmp; \
	else \
		mv $@.tmp $@; \
	fi

all: archive

native: $(NATIVE_BINS)

archive: $(ARCHIVE)

full-native: native

full-archive: $(FULL_ARCHIVE)

$(BUILD)/native/null_data.o: native/null_data.S $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

$(BUILD)/native/medium/null_data.o: native/null_data.S $(NATIVE_MEDIUM_LD)
	@mkdir -p $(dir $@)
	$(CC) $(NATIVE_MEDIUM_CFLAGS) -c $< -o $@

$(BUILD)/native/server/null_data.o: native/null_data.S $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/libanx/%.o: libanx/%.c libanx/anx_trap.h libanx/anx_native.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

$(BUILD)/native/medium/libanx/%.o: libanx/%.c libanx/anx_trap.h libanx/anx_native.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(NATIVE_MEDIUM_CFLAGS) -c $< -o $@

$(BUILD)/native/server/libanx/%.o: libanx/%.c libanx/anx_trap.h libanx/anx_native.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/server/lib/bit/bit_string.o: ../kern/lib/bit/bit_string.c ../kern/lib/bit/bit_string.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/apps/%.o: apps/%.c libanx/anx_native.h apps/netapp_common.h apps/antler_nettools.h apps/oss_common.h apps/driverctl_common.h apps/fdc_tool_common.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(CFLAGS) -c $< -o $@

# The HTTPS fetcher is compiled with the medium memory model: BearSSL needs
# real 32-bit long arithmetic and more than one small-model code segment.
$(BUILD)/native/apps/antler_https.o: apps/antler_https.c libanx/anx_native.h apps/netapp_common.h $(BEARSSL_SRCS) $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(NATIVE_MEDIUM_CFLAGS) -c $< -o $@

$(BUILD)/native/apps/antler_init.o: apps/init/boot_display.h
$(BUILD)/native/apps/init/boot_display.o: apps/init/boot_display.h

# vfs.c is the neutral filesystem router linked only by fsys.  It carries no
# format personality: ext2, FAT, and NFS requests are forwarded to their
# owning services (ext2fs, fatfs, nfs) over IPC.
$(BUILD)/native/servers/filesystem/core/vfs.o: \
	$(SERVER_SRC_ROOT)/filesystem/core/vfs.c \
	$(SERVER_SRC_ROOT)/common/server_common.h libanx/anx_native.h \
	$(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -fno-inline -c $< -o $@

$(BUILD)/native/servers/filesystem/core/ext2/%.o: \
	$(SERVER_SRC_ROOT)/filesystem/core/ext2/%.c \
	$(EXT2_INTERNAL_HEADERS) $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -fno-inline \
		-Wno-int-to-pointer-cast -Wno-pointer-to-int-cast -c $< -o $@

$(BUILD)/native/servers/%.o: $(SERVER_SRC_ROOT)/%.c $(SERVER_SRC_ROOT)/common/server_common.h libanx/anx_native.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/servers/%.o: $(SERVER_SRC_ROOT)/%.S $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/servers/driverd/%.o: \
	$(SERVER_SRC_ROOT)/driverd/%.c $(DRIVERD_INTERNAL_HEADERS) \
	$(SERVER_SRC_ROOT)/common/server_common.h libanx/anx_native.h \
	$(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -c $< -o $@

$(BUILD)/native/servers/fsys/%.o: $(SERVER_SRC_ROOT)/fsys/%.c \
	$(FSYS_INTERNAL_HEADERS) $(SERVER_SRC_ROOT)/common/server_common.h \
	libanx/anx_native.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
ifeq ($(FSYS_TRACE_COM2),1)
	$(CC) $(SERVER_CFLAGS) -fno-inline-functions-called-once -fno-inline-small-functions -c $< -o $@
else
	$(CC) $(SERVER_CFLAGS) -fno-inline-functions-called-once -fno-inline-small-functions -UANTLER_SERVER_TRACE_COM2 -DANTLER_SERVER_TRACE_COM2=0 -c $< -o $@
endif

$(BUILD)/native/servers/common/server_trace_nocom2.o: $(SERVER_SRC_ROOT)/common/server_trace.c $(SERVER_SRC_ROOT)/common/server_trace.h $(BUILD_CONFIG) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(SERVER_CFLAGS) -UANTLER_SERVER_TRACE_COM2 -DANTLER_SERVER_TRACE_COM2=0 -c $< -o $@


.PHONY: native-libc

native-libc:
	$(MAKE) -C libc BUILD=$(LIBC_BUILD) USERLAND_MEMMODEL=$(USERLAND_MEMMODEL)

$(LIBC_A) $(LIBC_CRT0): native-libc

# Build the vendored BearSSL tree into one medium-model static archive with
# the Antler freestanding flags; the HTTPS helper is its only consumer.
$(BEARSSL_A): $(BEARSSL_SRCS) $(BEARSSL_ROOT)/Makefile $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	$(MAKE) -C $(BEARSSL_ROOT) -f Makefile \
		BUILD=$(BEARSSL_BUILD) BEARSSLLIB=$(abspath $@) \
		CC=$(CC) AR='$(AR) -rcs' CFLAGS='$(BEARSSL_CFLAGS)' \
		LDFLAGS='' $(abspath $@)

define ELKS_REAL_COMMAND_RULE
$(BUILD)/native/elks/$(1).o: $(2) $(BUILD_CONFIG) $(LIBC_A) $(LIBC_CRT0) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $$(dir $$@)
	$$(CC) $$(ELKS_REAL_CFLAGS) $$(ELKS_REAL_CFLAGS_$(1)) -c $$< -o $$@

$(BUILD)/native/elks/$(1).elf: $(BUILD)/native/elks/$(1).o $$(ELKS_REAL_EXTRA_OBJS_$(1)) $(LIBC_A) $(LIBC_CRT0) $(NATIVE_LD)
	@mkdir -p $$(dir $$@)
		$$(LD) $$(LDFLAGS) -T $$(NATIVE_LD) -o $$@ $$(LIBC_CRT0) $$< $$(ELKS_REAL_EXTRA_OBJS_$(1)) $$(LIBC_A) $$(NATIVE_LIBGCC)

$(BUILD)/bin/$(1): $(BUILD)/native/elks/$(1).text $(BUILD)/native/elks/$(1).data $(BUILD)/native/elks/$(1).elf $(MKANTLER)
	@mkdir -p $$(dir $$@)
	$$(MKANTLER) $(BUILD)/native/elks/$(1).text $(BUILD)/native/elks/$(1).data $$@ \
		$(BUILD)/native/elks/$(1).elf $$(NM) $$(USERLAND_MEMMODEL)
endef

$(foreach cmd,$(ELKS_REAL_COMMANDS), \
  $(eval $(call ELKS_REAL_COMMAND_RULE,$(cmd),$(ELKS_REAL_SRC_$(cmd)))))

$(BUILD)/native/elks/antler_compat.o: \
	$(SERVER_SRC_ROOT)/fsys/service/fsys_mem.h

$(BUILD)/native/elks/ash/bltin/%.o: $(ELKS_APP_ROOT)/ash/bltin/%.c $(BUILD_CONFIG) $(LIBC_A) $(LIBC_CRT0) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(ELKS_ASH_CFLAGS) -c $< -o $@

$(BUILD)/native/elks/ash/%.o: $(ELKS_APP_ROOT)/ash/%.c $(BUILD_CONFIG) $(LIBC_A) $(LIBC_CRT0) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(ELKS_ASH_CFLAGS) -c $< -o $@

$(BUILD)/native/elks/sh.elf: $(ELKS_ASH_OBJ_PATHS) $(LIBC_A) $(LIBC_CRT0) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(LIBC_CRT0) $(ELKS_ASH_OBJ_PATHS) $(LIBC_A) $(NATIVE_LIBGCC)

$(BUILD)/bin/sh: $(BUILD)/native/elks/sh.text $(BUILD)/native/elks/sh.data $(BUILD)/native/elks/sh.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/elks/sh.text $(BUILD)/native/elks/sh.data $@ \
		$(BUILD)/native/elks/sh.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/native/elks/sash/%.o: $(ELKS_APP_ROOT)/sash/%.c \
	$(ELKS_APP_ROOT)/sash/sash.h $(ELKS_APP_ROOT)/sash/config.h \
	$(BUILD_CONFIG) $(LIBC_A) $(LIBC_CRT0) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(ELKS_SASH_CFLAGS) -c $< -o $@

$(BUILD)/native/elks/sash.elf: $(ELKS_SASH_OBJ_PATHS) $(LIBC_A) $(LIBC_CRT0) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(LIBC_CRT0) $(ELKS_SASH_OBJ_PATHS) $(LIBC_A) $(NATIVE_LIBGCC)

$(BUILD)/bin/sash: $(BUILD)/native/elks/sash.text $(BUILD)/native/elks/sash.data $(BUILD)/native/elks/sash.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/elks/sash.text $(BUILD)/native/elks/sash.data $@ \
		$(BUILD)/native/elks/sash.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/native/elks/elvis/%.o: $(ELKS_APP_ROOT)/elvis/%.c $(BUILD_CONFIG) $(LIBC_A) $(LIBC_CRT0) $(USERLAND_PUBLIC_HEADERS)
	@mkdir -p $(dir $@)
	$(CC) $(ELKS_ELVIS_CFLAGS) -c $< -o $@

$(BUILD)/native/elks/vi.elf: $(ELKS_ELVIS_OBJ_PATHS) $(LIBC_A) $(LIBC_CRT0) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(LIBC_CRT0) $(ELKS_ELVIS_OBJ_PATHS) $(LIBC_A) $(NATIVE_LIBGCC)

$(BUILD)/bin/vi: $(BUILD)/native/elks/vi.text $(BUILD)/native/elks/vi.data $(BUILD)/native/elks/vi.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/elks/vi.text $(BUILD)/native/elks/vi.data $@ \
		$(BUILD)/native/elks/vi.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/native/apps/service.o: CFLAGS += -fno-omit-frame-pointer

NATIVE_INIT_OBJS := \
	$(BUILD)/native/apps/antler_init.o \
	$(BUILD)/native/apps/init/boot_display.o

$(BUILD)/native/antler_init.elf: $(NATIVE_INIT_OBJS) $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(NATIVE_INIT_OBJS) $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/anx2ctl.elf: $(BUILD)/native/apps/anx2ctl.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/anx2ctl.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/service.elf: $(BUILD)/native/apps/service.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/service.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/modprobe.elf: $(BUILD)/native/apps/modprobe.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/modprobe.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/dmesg.elf: $(BUILD)/native/apps/dmesg.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/dmesg.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/segmap.elf: $(BUILD)/native/apps/segmap.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/segmap.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/mount.elf: $(BUILD)/native/apps/mount.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/mount.o $(NATIVE_BASE_LIB_OBJS)

$(BUILD)/native/umount.elf: $(BUILD)/native/apps/umount.o $(NATIVE_BASE_LIB_OBJS) $(NATIVE_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_LD) -o $@ $(BUILD)/native/apps/umount.o $(NATIVE_BASE_LIB_OBJS)

# Medium-model HTTPS helper: link against the medium libanx objects and the
# BearSSL archive, with libgcc for the 32-bit helper routines TLS needs.
$(BUILD)/native/antler_https.elf: $(BUILD)/native/apps/antler_https.o $(NATIVE_MEDIUM_BASE_LIB_OBJS) $(BEARSSL_A) $(NATIVE_MEDIUM_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(NATIVE_MEDIUM_LD) -o $@ \
		$(BUILD)/native/apps/antler_https.o \
		$(NATIVE_MEDIUM_BASE_LIB_OBJS) $(BEARSSL_A) $(NATIVE_LIBGCC)

$(BUILD)/bin/https: $(BUILD)/native/antler_https.text $(BUILD)/native/antler_https.data $(BUILD)/native/antler_https.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/antler_https.text $(BUILD)/native/antler_https.data $@ \
		$(BUILD)/native/antler_https.elf $(NM) medium

define NATIVE_DIRECT_COMMAND_RULE
$(BUILD)/native/$(1).elf: $(BUILD)/native/apps/$(1).o $(NATIVE_BASE_LIB_OBJS) $$(NATIVE_DIRECT_EXTRA_OBJS_$(1)) $(NATIVE_LD)
	@mkdir -p $$(dir $$@)
		$$(LD) $$(LDFLAGS) -T $$(NATIVE_LD) -o $$@ $$< $$(NATIVE_BASE_LIB_OBJS) $$(NATIVE_DIRECT_EXTRA_OBJS_$(1))

$(BUILD)/bin/$(1): $(BUILD)/native/$(1).text $(BUILD)/native/$(1).data $(BUILD)/native/$(1).elf $(MKANTLER)
	@mkdir -p $$(dir $$@)
	$$(MKANTLER) $(BUILD)/native/$(1).text $(BUILD)/native/$(1).data $$@ \
		$(BUILD)/native/$(1).elf $$(NM) $$(USERLAND_MEMMODEL)
endef

$(foreach cmd,$(NATIVE_DIRECT_COMMANDS), \
  $(eval $(call NATIVE_DIRECT_COMMAND_RULE,$(cmd))))

$(BUILD)/native/%.text: $(BUILD)/native/%.elf $(NO_BIOS_AUDIT)
	$(NO_BIOS_AUDIT_RUN) $(abspath $<)
	$(OBJCOPY) -O binary -j .text $< $@

$(BUILD)/native/%.data: $(BUILD)/native/%.elf
	$(OBJCOPY) -O binary -j .data $< $@

$(BUILD)/bin/antler-init: $(BUILD)/native/antler_init.text $(BUILD)/native/antler_init.data $(BUILD)/native/antler_init.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/antler_init.text $(BUILD)/native/antler_init.data $@ \
		$(BUILD)/native/antler_init.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/anx2ctl: $(BUILD)/native/anx2ctl.text $(BUILD)/native/anx2ctl.data $(BUILD)/native/anx2ctl.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/anx2ctl.text $(BUILD)/native/anx2ctl.data $@ \
		$(BUILD)/native/anx2ctl.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/fsys: $(BUILD)/native/fsys.text $(BUILD)/native/fsys.data $(BUILD)/native/fsys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/fsys.text $(BUILD)/native/fsys.data $@ \
		$(BUILD)/native/fsys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/ext2fs: $(BUILD)/native/ext2fs.text $(BUILD)/native/ext2fs.data $(BUILD)/native/ext2fs.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/ext2fs.text $(BUILD)/native/ext2fs.data $@ \
		$(BUILD)/native/ext2fs.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/fatfs: $(BUILD)/native/fatfs.text $(BUILD)/native/fatfs.data $(BUILD)/native/fatfs.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/fatfs.text $(BUILD)/native/fatfs.data $@ \
		$(BUILD)/native/fatfs.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/netsys: $(BUILD)/native/netsys.text $(BUILD)/native/netsys.data $(BUILD)/native/netsys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/netsys.text $(BUILD)/native/netsys.data $@ \
		$(BUILD)/native/netsys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/nativesys: $(BUILD)/native/nativesys.text $(BUILD)/native/nativesys.data $(BUILD)/native/nativesys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/nativesys.text $(BUILD)/native/nativesys.data $@ \
		$(BUILD)/native/nativesys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/sersys: $(BUILD)/native/sersys.text $(BUILD)/native/sersys.data $(BUILD)/native/sersys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/sersys.text $(BUILD)/native/sersys.data $@ \
		$(BUILD)/native/sersys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/keysys: $(BUILD)/native/keysys.text $(BUILD)/native/keysys.data $(BUILD)/native/keysys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/keysys.text $(BUILD)/native/keysys.data $@ \
		$(BUILD)/native/keysys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/pointersys: $(BUILD)/native/pointersys.text $(BUILD)/native/pointersys.data $(BUILD)/native/pointersys.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/pointersys.text \
		$(BUILD)/native/pointersys.data $@ \
		$(BUILD)/native/pointersys.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/ramdiskd: $(BUILD)/native/ramdiskd.text $(BUILD)/native/ramdiskd.data $(BUILD)/native/ramdiskd.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/ramdiskd.text $(BUILD)/native/ramdiskd.data $@ \
		$(BUILD)/native/ramdiskd.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/driverd: $(BUILD)/native/driverd.text $(BUILD)/native/driverd.data $(BUILD)/native/driverd.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/driverd.text $(BUILD)/native/driverd.data $@ \
		$(BUILD)/native/driverd.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/ipserial: $(BUILD)/native/ipserial.text $(BUILD)/native/ipserial.data $(BUILD)/native/ipserial.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/ipserial.text $(BUILD)/native/ipserial.data $@ \
		$(BUILD)/native/ipserial.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/bin/nfs: $(BUILD)/native/nfs.text $(BUILD)/native/nfs.data $(BUILD)/native/nfs.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/nfs.text $(BUILD)/native/nfs.data $@ \
		$(BUILD)/native/nfs.elf $(NM) $(USERLAND_SERVER_MEMMODEL)

$(BUILD)/native/fsys.elf: $(FSYS_SERVICE_OBJS) $(FSYS_SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(FSYS_SERVICE_OBJS) $(FSYS_SERVER_BASE_LIB_OBJS)

$(BUILD)/native/ext2fs.elf: $(EXT2FS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(BUILD)/native/server/lib/bit/bit_string.o $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(EXT2FS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(BUILD)/native/server/lib/bit/bit_string.o

$(BUILD)/native/fatfs.elf: $(FATFS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(BUILD)/native/server/lib/bit/bit_string.o $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(FATFS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(BUILD)/native/server/lib/bit/bit_string.o

$(BUILD)/native/netsys.elf: $(NETSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(NETSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/nativesys.elf: $(NATIVESYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(NATIVESYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/sersys.elf: $(SERSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(SERSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/keysys.elf: $(KEYSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ \
		$(KEYSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/pointersys.elf: $(POINTERSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ \
		$(POINTERSYS_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/ramdiskd.elf: $(BUILD)/native/servers/ramdisk/service/main.o $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(BUILD)/native/servers/ramdisk/service/main.o $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/driverd.elf: $(DRIVERD_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(DRIVERD_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/ipserial.elf: $(IPSERIAL_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(IPSERIAL_SERVICE_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/native/nfs.elf: $(NFS_SERVER_OBJS) $(SERVER_BASE_LIB_OBJS) $(SERVER_LD)
	@mkdir -p $(dir $@)
	$(LD) $(LDFLAGS) -T $(SERVER_LD) -o $@ $(NFS_SERVER_OBJS) $(SERVER_BASE_LIB_OBJS)

$(BUILD)/bin/service: $(BUILD)/native/service.text $(BUILD)/native/service.data $(BUILD)/native/service.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/service.text $(BUILD)/native/service.data $@ \
		$(BUILD)/native/service.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/modprobe: $(BUILD)/native/modprobe.text $(BUILD)/native/modprobe.data $(BUILD)/native/modprobe.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/modprobe.text $(BUILD)/native/modprobe.data $@ \
		$(BUILD)/native/modprobe.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/dmesg: $(BUILD)/native/dmesg.text $(BUILD)/native/dmesg.data $(BUILD)/native/dmesg.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/dmesg.text $(BUILD)/native/dmesg.data $@ \
		$(BUILD)/native/dmesg.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/segmap: $(BUILD)/native/segmap.text $(BUILD)/native/segmap.data $(BUILD)/native/segmap.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/segmap.text $(BUILD)/native/segmap.data $@ \
		$(BUILD)/native/segmap.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/mount: $(BUILD)/native/mount.text $(BUILD)/native/mount.data $(BUILD)/native/mount.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/mount.text $(BUILD)/native/mount.data $@ \
		$(BUILD)/native/mount.elf $(NM) $(USERLAND_MEMMODEL)

$(BUILD)/bin/umount: $(BUILD)/native/umount.text $(BUILD)/native/umount.data $(BUILD)/native/umount.elf $(MKANTLER)
	@mkdir -p $(dir $@)
	$(MKANTLER) $(BUILD)/native/umount.text $(BUILD)/native/umount.data $@ \
		$(BUILD)/native/umount.elf $(NM) $(USERLAND_MEMMODEL)

$(MKBOOTAR): tools/mkbootar.c
	@mkdir -p $(dir $@)
	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<

$(MKANTLER): tools/mkantler.c
	@mkdir -p $(dir $@)
	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<

FULL_ROOTFS_ARGS := \
	sbin/init=$(INIT_BIN) \
	$(NATIVE_ARCHIVE_ARGS) \
	$(ANX2_SERVICE_ARCHIVE_ARGS) \
	$(HD_ROOT_ARCHIVE_ARGS) \
	$(ROOT_ARCHIVE_ARGS) \
	$(ARCHIVE_EXTRA_ARGS)

$(FULL_ARCHIVE): $(MKBOOTAR) $(NATIVE_BINS) $(ROOT_ARCHIVE_FILES) $(ROOT_GENERATED_FILES) $(HD_ROOT_ARCHIVE_FILES) $(HD_ROOT_GENERATED_FILES) $(ARCHIVE_EXTRA_DEPS)
	$(MKBOOTAR) $@ $(FULL_ROOTFS_ARGS)

rootfs-debugfs-script: $(FULL_ARCHIVE)
	@mkdir -p $(dir $(ROOTFS_DEBUGFS_SCRIPT))
	@rm -f $(ROOTFS_DEBUGFS_SCRIPT).tmp $(ROOTFS_DEBUGFS_SCRIPT).all \
		$(ROOTFS_DEBUGFS_SCRIPT).seen $(ROOTFS_DEBUGFS_SCRIPT).dstseen
	@{ \
		for spec in $(FULL_ROOTFS_ARGS); do \
			name=$${spec%%=*}; \
			dir=$${name%/*}; \
			if test "$$dir" != "$$name"; then \
				path=; oldifs=$$IFS; IFS=/; \
				for part in $$dir; do \
					if test -n "$$part"; then \
						if test -n "$$path"; then path=$$path/$$part; \
						else path=$$part; fi; \
						printf 'mkdir /%s\n' "$$path"; \
						printf 'sif /%s mode 040755\n' "$$path"; \
						printf 'sif /%s uid 0\n' "$$path"; \
						printf 'sif /%s gid 0\n' "$$path"; \
					fi; \
				done; \
				IFS=$$oldifs; \
			fi; \
		done; \
	} | awk '!seen[$$0]++' > $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@printf 'expand_dir /bin\nexpand_dir /bin\n' \
		>> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@printf 'expand_dir /sbin\nexpand_dir /usr/bin\n' \
		>> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@for spec in $(FULL_ROOTFS_ARGS); do \
		name=$${spec%%=*}; src=$${spec#*=}; dst=/$${name}; \
		file_mode=0644; file_uid=0; file_gid=0; \
		case "$$src" in \
		/*) ;; \
		*) src=$(CURDIR)/$$src ;; \
		esac; \
		case "$$dst" in \
		/bin/*|/sbin/*|/usr/bin/*|/system/servers/*) \
			file_mode=0555 ;; \
		/system/drivers/*) \
			file_mode=0555 ;; \
		esac; \
		case "$$dst" in \
		/home/user1|/home/user1/*) \
			file_uid=101; file_gid=100 ;; \
		/home/user2|/home/user2/*) \
			file_uid=102; file_gid=100 ;; \
		esac; \
		if grep -Fxq "$$dst" $(ROOTFS_DEBUGFS_SCRIPT).dstseen \
			2>/dev/null; then \
			continue; \
		fi; \
		printf '%s\n' "$$dst" >> $(ROOTFS_DEBUGFS_SCRIPT).dstseen; \
		first=$$(awk -F '\t' -v s="$$src" '$$1 == s { print $$2; exit }' \
			$(ROOTFS_DEBUGFS_SCRIPT).seen 2>/dev/null); \
		printf '%s\t%s\n' "$$src" "$$dst" >> $(ROOTFS_DEBUGFS_SCRIPT).all; \
		if test -n "$$first"; then \
			if test "$$first" != "$$dst"; then \
				printf 'ln %s %s\n' "$$first" "$$dst" \
					>> $(ROOTFS_DEBUGFS_SCRIPT).tmp; \
			fi; \
		else \
			printf '%s\t%s\n' "$$src" "$$dst" >> $(ROOTFS_DEBUGFS_SCRIPT).seen; \
			printf 'write %s %s\n' "$$src" "$$dst" >> $(ROOTFS_DEBUGFS_SCRIPT).tmp; \
			printf 'sif %s mode 010%s\n' "$$dst" "$$file_mode" \
				>> $(ROOTFS_DEBUGFS_SCRIPT).tmp; \
			printf 'sif %s uid %s\n' "$$dst" "$$file_uid" \
				>> $(ROOTFS_DEBUGFS_SCRIPT).tmp; \
			printf 'sif %s gid %s\n' "$$dst" "$$file_gid" \
				>> $(ROOTFS_DEBUGFS_SCRIPT).tmp; \
		fi; \
	done
	@printf 'mkdir /tmp\nmkdir /root\nmkdir /home\nmkdir /home/user1\nmkdir /home/user2\nmkdir /netboot\nmkdir /var\nmkdir /var/log\nmkdir /dev\nmkdir /mnt\nmkdir /mnt/mfm\nmkdir /mnt/floppy\nmkdir /mnt/fd0\nmkdir /mnt/fd1\nmkdir /mnt/nfs\n' \
		>> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@printf 'sif /tmp mode 041777\nsif /root mode 040700\nsif /home mode 040755\nsif /home/user1 mode 040755\nsif /home/user2 mode 040755\nsif /netboot mode 040755\nsif /var mode 040755\nsif /var/log mode 040755\nsif /dev mode 040755\nsif /mnt mode 040755\nsif /mnt/mfm mode 040755\nsif /mnt/floppy mode 040755\nsif /mnt/nfs mode 040755\n' \
		>> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@printf 'sif /tmp uid 0\nsif /tmp gid 0\nsif /root uid 0\nsif /root gid 0\nsif /home uid 0\nsif /home gid 0\nsif /home/user1 uid 101\nsif /home/user1 gid 100\nsif /home/user2 uid 102\nsif /home/user2 gid 100\nsif /netboot uid 0\nsif /netboot gid 0\nsif /var uid 0\nsif /var gid 0\nsif /var/log uid 0\nsif /var/log gid 0\nsif /dev uid 0\nsif /dev gid 0\nsif /mnt uid 0\nsif /mnt gid 0\nsif /mnt/mfm uid 0\nsif /mnt/mfm gid 0\nsif /mnt/floppy uid 0\nsif /mnt/floppy gid 0\nsif /mnt/nfs uid 0\nsif /mnt/nfs gid 0\n' \
		>> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@{ \
		printf 'cd /dev\n'; \
		printf 'mknod hda b 3 0\n'; \
		printf 'mknod hda1 b 3 1\n'; \
		printf 'mknod hda2 b 3 2\n'; \
		printf 'mknod hda3 b 3 3\n'; \
		printf 'mknod hda4 b 3 4\n'; \
		printf 'mknod mfm0 b 7 0\n'; \
		printf 'mknod mfm0p1 b 7 1\n'; \
		printf 'mknod mfm1 b 7 8\n'; \
		printf 'mknod mfm1p1 b 7 9\n'; \
		printf 'mknod mfm2 b 7 16\n'; \
		printf 'mknod mfm2p1 b 7 17\n'; \
		printf 'mknod mfm3 b 7 24\n'; \
		printf 'mknod mfm3p1 b 7 25\n'; \
		printf 'mknod fd0 b 3 32\n'; \
		printf 'mknod fd1 b 3 40\n'; \
		printf 'mknod js0 c 15 0\n'; \
		printf 'mknod df0 b 4 0\n'; \
		printf 'mknod df1 b 4 1\n'; \
		printf 'mknod cfa b 5 0\n'; \
		printf 'mknod cfa1 b 5 1\n'; \
		printf 'mknod cfa2 b 5 2\n'; \
		printf 'mknod cfa3 b 5 3\n'; \
		printf 'mknod cfa4 b 5 4\n'; \
		printf 'mknod ata b 5 0\n'; \
		printf 'mknod ata1 b 5 1\n'; \
		printf 'mknod ata2 b 5 2\n'; \
		printf 'mknod ata3 b 5 3\n'; \
		printf 'mknod ata4 b 5 4\n'; \
		printf 'mknod mem c 1 1\n'; \
		printf 'mknod kmem c 1 2\n'; \
		printf 'mknod null c 1 3\n'; \
		printf 'mknod port c 1 4\n'; \
		printf 'mknod memport c 1 6\n'; \
		printf 'mknod zero c 1 5\n'; \
		printf 'mknod ptyp0 c 2 8\n'; \
		printf 'mknod ptyp1 c 2 9\n'; \
		printf 'mknod ptyp2 c 2 10\n'; \
		printf 'mknod ptyp3 c 2 11\n'; \
		printf 'mknod ttyp0 c 4 8\n'; \
		printf 'mknod ttyp1 c 4 9\n'; \
		printf 'mknod ttyp2 c 4 10\n'; \
		printf 'mknod ttyp3 c 4 11\n'; \
			printf 'mknod ttyS0 c 4 64\n'; \
			printf 'mknod ttyS1 c 4 65\n'; \
			printf 'mknod ttyS2 c 4 66\n'; \
			printf 'mknod ttyS3 c 4 67\n'; \
			printf 'mknod ipserial c 4 80\n'; \
		printf 'mknod tty c 4 255\n'; \
		printf 'mknod dsp c 5 0\n'; \
		printf 'mknod audio c 5 0\n'; \
		printf 'mknod netdev c 8 0\n'; \
		printf 'mknod ne0 c 9 0\n'; \
		printf 'mknod wd0 c 9 1\n'; \
		printf 'mknod 3c0 c 9 2\n'; \
		printf 'mknod ul0 c 9 3\n'; \
		printf 'cd /\n'; \
		printf 'sif /dev/hda mode 060660\n'; \
		printf 'sif /dev/hda1 mode 060660\n'; \
		printf 'sif /dev/hda2 mode 060660\n'; \
		printf 'sif /dev/hda3 mode 060660\n'; \
		printf 'sif /dev/hda4 mode 060660\n'; \
		printf 'sif /dev/mfm0 mode 060660\n'; \
		printf 'sif /dev/mfm0p1 mode 060660\n'; \
		printf 'sif /dev/mfm1 mode 060660\n'; \
		printf 'sif /dev/mfm1p1 mode 060660\n'; \
		printf 'sif /dev/mfm2 mode 060660\n'; \
		printf 'sif /dev/mfm2p1 mode 060660\n'; \
		printf 'sif /dev/mfm3 mode 060660\n'; \
		printf 'sif /dev/mfm3p1 mode 060660\n'; \
		printf 'sif /dev/fd0 mode 060660\n'; \
		printf 'sif /dev/fd1 mode 060660\n'; \
		printf 'sif /dev/js0 mode 020660\n'; \
		printf 'sif /dev/df0 mode 060660\n'; \
		printf 'sif /dev/df1 mode 060660\n'; \
		printf 'sif /dev/cfa mode 060660\n'; \
		printf 'sif /dev/cfa1 mode 060660\n'; \
		printf 'sif /dev/cfa2 mode 060660\n'; \
		printf 'sif /dev/cfa3 mode 060660\n'; \
		printf 'sif /dev/cfa4 mode 060660\n'; \
		printf 'sif /dev/ata mode 060660\n'; \
		printf 'sif /dev/ata1 mode 060660\n'; \
		printf 'sif /dev/ata2 mode 060660\n'; \
		printf 'sif /dev/ata3 mode 060660\n'; \
		printf 'sif /dev/ata4 mode 060660\n'; \
		printf 'sif /dev/mem mode 020600\n'; \
		printf 'sif /dev/kmem mode 020600\n'; \
		printf 'sif /dev/null mode 020666\n'; \
		printf 'sif /dev/port mode 020600\n'; \
		printf 'sif /dev/memport mode 020600\n'; \
		printf 'sif /dev/zero mode 020666\n'; \
		printf 'sif /dev/ptyp0 mode 020666\n'; \
		printf 'sif /dev/ptyp1 mode 020666\n'; \
		printf 'sif /dev/ptyp2 mode 020666\n'; \
		printf 'sif /dev/ptyp3 mode 020666\n'; \
		printf 'sif /dev/ttyp0 mode 020666\n'; \
		printf 'sif /dev/ttyp1 mode 020666\n'; \
		printf 'sif /dev/ttyp2 mode 020666\n'; \
		printf 'sif /dev/ttyp3 mode 020666\n'; \
			printf 'sif /dev/ttyS0 mode 020666\n'; \
			printf 'sif /dev/ttyS1 mode 020666\n'; \
			printf 'sif /dev/ttyS2 mode 020666\n'; \
			printf 'sif /dev/ttyS3 mode 020666\n'; \
			printf 'sif /dev/ipserial mode 020666\n'; \
		printf 'sif /dev/tty mode 020666\n'; \
		printf 'sif /dev/dsp mode 020666\n'; \
		printf 'sif /dev/audio mode 020666\n'; \
		printf 'sif /dev/netdev mode 020660\n'; \
		printf 'sif /dev/ne0 mode 020660\n'; \
		printf 'sif /dev/wd0 mode 020660\n'; \
		printf 'sif /dev/3c0 mode 020660\n'; \
		printf 'sif /dev/ul0 mode 020660\n'; \
	} >> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@awk -F '\t' ' \
		{ key = $$1 "\t" $$2; if (seen[key]++) next; \
		  count[$$1]++; if (!($$1 in first)) first[$$1] = $$2; } \
		END { for (src in count) if (count[src] > 1) \
			printf "sif %s links_count %u\n", first[src], count[src]; }' \
		$(ROOTFS_DEBUGFS_SCRIPT).all >> $(ROOTFS_DEBUGFS_SCRIPT).tmp
	@mv $(ROOTFS_DEBUGFS_SCRIPT).tmp $(ROOTFS_DEBUGFS_SCRIPT)
	@rm -f $(ROOTFS_DEBUGFS_SCRIPT).all $(ROOTFS_DEBUGFS_SCRIPT).seen

$(BUILD)/root/boot/cmdline: Makefile $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@printf 'root=%s %s' '$(ROOT_DEVICE)' '$(ROOT_FLAGS)' > $@
	@if [ -n '$(BOOT_OPTIONS)' ]; then printf ' %s' '$(BOOT_OPTIONS)' >> $@; fi
	@printf ' init=/sbin/init\n' >> $@

$(BUILD)/root/etc/fstab: Makefile $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@printf '# <file system> <mount point> <type> <options> <dump> <pass>\n' > $@
	@printf '# Examples:\n' >> $@
	@printf '# /dev/mfm0p1 /mnt/mfm ext2 rw 0 0\n' >> $@
	@printf '# /dev/hda1 /mnt/xtide ext2 rw 0 0\n' >> $@
	@printf '# /dev/fd0 /mnt/floppy fat ro 0 0\n' >> $@
	@printf '# hulk:/mnt/srv/Antler /mnt/nfs nfs rw 0 0\n' >> $@
	@printf '%s / %s %s 0 1\n' '$(ROOT_DEVICE)' '$(ROOT_FS_TYPE)' '$(ROOT_FLAGS)' >> $@
	@if test "$(ENABLE_NFS)" = "1"; then \
		printf '%s:%s %s nfs rw,noauto 0 0\n' \
			'$(NFS_SERVER)' '$(NFS_EXPORT)' '$(NFS_MOUNTPOINT)' >> $@; \
	fi

$(BUILD)/root/config/sys.init: Makefile root/config/sys.init $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@network_requested=no; \
	if test "$(START_NETWORK_ON_BOOT)" = "1"; then network_requested=yes; fi; \
	if test "$(NTP_ENABLE)" = "1" \
		-o "$(NTP_ENABLE)" = "yes"; then network_requested=yes; fi; \
	if test "$(NFS_START_NETWORK_ON_BOOT)" = "1" \
		-o "$(NFS_START_NETWORK_ON_BOOT)" = "yes"; then network_requested=yes; fi; \
	if test "$(ESD_ENABLE)" = "1" \
		-o "$(ESD_ENABLE)" = "yes"; then network_requested=yes; fi; \
	{ \
		printf '%s\n' '# ANX2-style system initialization command file.'; \
		printf '%s\n' '# Generated from build policy.'; \
			if test "$(ENABLE_NETWORK)" = "1" \
				&& test "$$network_requested" = "yes"; then \
				printf '%s\n' '# Synchronous: netsys+netpoll must claim their top-of-window' ; \
				printf '%s\n' '# arenas before inittab spawns gemlogin, or the login image' ; \
				printf '%s\n' '# lands between them and its exit splits the single free hole' ; \
				printf '%s\n' '# gemdesk needs for its transactional exec on 640KB machines.' ; \
				printf '%s\n' '/bin/net boot'; \
			else \
				printf '%s\n' '# no boot network services requested'; \
			fi; \
			if test "$(ENABLE_NETWORK)" = "1" \
				&& { test "$(IPSERIAL_ENABLE)" = "1" \
					-o "$(IPSERIAL_ENABLE)" = "yes"; }; then \
				printf '%s\n' '/bin/sh /etc/init.d/ipserial boot'; \
			fi; \
			if test -n '$(SYSINIT_EXTRA_LINE)'; then \
				printf '%s\n' '$(SYSINIT_EXTRA_LINE)'; \
			fi; \
		} > $@

$(BUILD)/root/etc/inittab: Makefile root/etc/inittab $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@sed 's/^id:[^:]*:initdefault:/id:$(GEM_RUNLEVEL):initdefault:/' \
		root/etc/inittab > $@

$(BUILD)/root/etc/default/tty: Makefile $(TTY_DEFAULTS) $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@cp "$(TTY_DEFAULTS)" $@

$(BUILD)/root/etc/default/gem-vdi: Makefile $(GEM_VDI_DEFAULTS) $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@cp "$(GEM_VDI_DEFAULTS)" $@

$(BUILD)/root/etc/rc.sys: Makefile root/etc/rc.sys $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@cp root/etc/rc.sys $@

$(BUILD)/root/etc/default/kernel: Makefile root/etc/default/kernel $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@cp root/etc/default/kernel $@

$(BUILD)/root/etc/default/drivers: Makefile $(DRIVER_DEFAULTS) $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@mfm_driver=no; \
	if test "$(ENABLE_MFM_DRIVER)" = "1"; then mfm_driver=yes; fi; \
	if test "$(ROOT_BLOCK_BACKEND)" = "mfm"; then \
		mfm_driver=yes; \
		sed -e 's/^[	 ]*BLOCK_DRIVER[	 ]*=.*/BLOCK_DRIVER=mfm/' \
			-e 's/^[	 ]*BLOCK_DRIVER_MODE[	 ]*=.*/BLOCK_DRIVER_MODE=$(if $(filter 1,$(MFM_IRQ_AWARE)),interrupt,polling)/' \
			-e 's/^[	 ]*DRIVER_XTIDE[	 ]*=.*/DRIVER_XTIDE=no/' \
			-e 's/^[	 ]*DRIVER_ATHD[	 ]*=.*/DRIVER_ATHD=no/' \
			-e "s/^[	 ]*DRIVER_MFM_ST506[	 ]*=.*/DRIVER_MFM_ST506=$$mfm_driver/" \
				-e 's/^[	 ]*MFM_ST506_MODE[	 ]*=.*/MFM_ST506_MODE=$(if $(filter 1,$(MFM_IRQ_AWARE)),interrupt,polling)/' \
				-e 's/^[	 ]*MFM_ST506_IRQ[	 ]*=.*/MFM_ST506_IRQ=$(MFM_ST506_IRQ)/' \
				-e 's/^[	 ]*MFM_ST506_DMA[	 ]*=.*/MFM_ST506_DMA=$(MFM_ST506_DMA)/' \
				-e 's/^[	 ]*MFM_ST506_DMA_MODE[	 ]*=.*/MFM_ST506_DMA_MODE=$(if $(filter 1,$(MFM_DMA_MODE)),yes,no)/' \
				"$(DRIVER_DEFAULTS)" > $@; \
	elif test "$(ROOT_BLOCK_BACKEND)" = "xtide" \
		-o "$(ROOT_BLOCK_BACKEND)" = "athd"; then \
		sed -e 's/^[	 ]*BLOCK_DRIVER[	 ]*=.*/BLOCK_DRIVER=$(ROOT_BLOCK_BACKEND)/' \
			-e 's/^[	 ]*BLOCK_DRIVER_MODE[	 ]*=.*/BLOCK_DRIVER_MODE=polling/' \
			-e 's/^[	 ]*DRIVER_XTIDE[	 ]*=.*/DRIVER_XTIDE=$(if $(filter xtide,$(ROOT_BLOCK_BACKEND)),yes,no)/' \
			-e 's/^[	 ]*DRIVER_ATHD[	 ]*=.*/DRIVER_ATHD=$(if $(filter athd,$(ROOT_BLOCK_BACKEND)),yes,no)/' \
			-e "s/^[	 ]*DRIVER_MFM_ST506[	 ]*=.*/DRIVER_MFM_ST506=$$mfm_driver/" \
				-e 's/^[	 ]*MFM_ST506_MODE[	 ]*=.*/MFM_ST506_MODE=$(if $(filter 1,$(MFM_IRQ_AWARE)),interrupt,polling)/' \
				-e 's/^[	 ]*MFM_ST506_IRQ[	 ]*=.*/MFM_ST506_IRQ=$(MFM_ST506_IRQ)/' \
				-e 's/^[	 ]*MFM_ST506_DMA[	 ]*=.*/MFM_ST506_DMA=$(MFM_ST506_DMA)/' \
				-e 's/^[	 ]*MFM_ST506_DMA_MODE[	 ]*=.*/MFM_ST506_DMA_MODE=$(if $(filter 1,$(MFM_DMA_MODE)),yes,no)/' \
				"$(DRIVER_DEFAULTS)" > $@; \
	fi
	@if test "$(ENABLE_NETWORK)" = "1"; then \
		sed -e 's/^[	 ]*DRIVER_ETHERNET[	 ]*=.*/DRIVER_ETHERNET=yes/' \
			$@ > $@.net; \
		mv $@.net $@; \
	fi
	@if test "$(SERSYS_TTYS0)$(SERSYS_TTYS1)$(SERSYS_TTYS2)$(SERSYS_TTYS3)" != "0000"; then \
		sed -e 's/^[	 ]*DRIVER_SERIAL[	 ]*=.*/DRIVER_SERIAL=yes/' \
			$@ > $@.serial; \
		mv $@.serial $@; \
	fi
	@sed -e '/^[	 ]*FS_POSIX_IPC_ENABLE[	 ]*=/d' $@ > $@.ipc
	@mv $@.ipc $@
	@printf '\nFS_POSIX_IPC_ENABLE=%s\n' \
		'$(if $(filter 1 yes,$(FS_POSIX_IPC_ENABLE)),1,0)' >> $@

$(BUILD)/root/etc/services.conf: Makefile root/etc/services.conf $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@service_network=no; \
	network_requested=no; \
	service_nfs=no; \
	service_sound=no; \
	start_sound=no; \
	service_ext2fs=$(if $(filter 1 yes,$(START_EXT2FS_ON_BOOT)),yes,no); \
	: NFS ships as /system/servers/nfs but remains manual on XT-class boots; \
	if test "$(ENABLE_NETWORK)" = "1"; then service_network=yes; fi; \
	if test "$(NFS_START_NETWORK_ON_BOOT)" = "1" \
		-o "$(NFS_START_NETWORK_ON_BOOT)" = "yes"; then network_requested=yes; fi; \
	if test "$(START_NETWORK_ON_BOOT)" = "1"; then network_requested=yes; fi; \
	if test "$(NTP_ENABLE)" = "1" \
		-o "$(NTP_ENABLE)" = "yes"; then network_requested=yes; fi; \
	if test "$(ENABLE_SOUND)" = "1" \
		&& { test "$(SOUND_SERVICE_ENABLE)" = "1" \
			-o "$(SOUND_SERVICE_ENABLE)" = "yes"; }; then \
		service_sound=yes; \
	fi; \
	if test "$$service_sound" = "yes" \
		&& { test "$(START_SOUND_ON_BOOT)" = "1" \
			-o "$(START_SOUND_ON_BOOT)" = "yes"; }; then \
		start_sound=yes; \
	fi; \
	start_network=no; \
	if test "$(ENABLE_NETWORK)" = "1" \
		&& test "$$network_requested" = "yes"; then \
		start_network=yes; \
	fi; \
		service_esd=$(if $(filter 1 yes,$(ESD_ENABLE)),yes,no); \
		sed -e "s/^[	 ]*SERVICE_NETWORK[	 ]*=.*/SERVICE_NETWORK=$$service_network/" \
		-e "s/^[	 ]*SERVICE_EXT2FS[	 ]*=.*/SERVICE_EXT2FS=$$service_ext2fs/" \
		-e "s/^[	 ]*SERVICE_NFS[	 ]*=.*/SERVICE_NFS=$$service_nfs/" \
		-e "s|^[	 ]*NFS_MOUNTPOINT[	 ]*=.*|NFS_MOUNTPOINT=$(NFS_MOUNTPOINT)|" \
		-e "s/^[	 ]*SERVICE_SOUND[	 ]*=.*/SERVICE_SOUND=$$service_sound/" \
		-e "s/^[	 ]*START_NETWORK[	 ]*=.*/START_NETWORK=$$start_network/" \
		-e "s/^[	 ]*START_SOUND[	 ]*=.*/START_SOUND=$$start_sound/" \
		-e "s/^[	 ]*SERVICE_IPSERIAL[	 ]*=.*/SERVICE_IPSERIAL=$(if $(filter 1 yes,$(IPSERIAL_ENABLE)),yes,no)/" \
			-e "s/^[	 ]*SERVICE_NTPDATE[	 ]*=.*/SERVICE_NTPDATE=$(if $(filter 1 yes,$(NTP_ENABLE)),yes,no)/" \
			-e "s/^[	 ]*SERVICE_ESD[	 ]*=.*/SERVICE_ESD=$$service_esd/" \
			root/etc/services.conf > $@

$(BUILD)/root/etc/network/interfaces: Makefile root/etc/network/interfaces $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@case "$(NET_DRIVER)" in \
	ne2k) link=ne0; device=/dev/ne0; driver=ne2k ;; \
	wd80x3) link=wd0; device=/dev/wd0; driver=wd80x3 ;; \
	el3) link=3c0; device=/dev/3c0; driver=el3 ;; \
	ultra) link=ul0; device=/dev/smc0; driver=ultra ;; \
	83c790qf) link=ul0; device=/dev/smc0; driver=83c790qf ;; \
	*) echo "unsupported NET_DRIVER=$(NET_DRIVER)" >&2; exit 1 ;; \
	esac; \
		method="$(NET_IPMODE)"; \
		case "$(NET_DHCP_ENABLE)" in yes|YES|true|TRUE|1) method=dhcp ;; esac; \
			sed -e "s/^iface \\(ne0\\|wd0\\|3c0\\|ul0\\) inet .*/iface $$link inet $$method/" \
		-e "s/^[	 ]*driver[	 ].*/	driver $$driver/" \
		-e "s|^[	 ]*device[	 ].*|	device $$device|" \
		-e 's/^[	 ]*hostname[	 ].*/	hostname $(NET_HOSTNAME)/' \
		-e 's/^[	 ]*address[	 ].*/	address $(NET_LOCALIP)/' \
		-e 's/^[	 ]*netmask[	 ].*/	netmask $(NET_NETMASK)/' \
		-e 's/^[	 ]*gateway[	 ].*/	gateway $(NET_GATEWAY)/' \
		-e 's/^[	 ]*dns-nameservers[	 ].*/	dns-nameservers $(NET_DNSSERVER)/' \
			-e 's/^[	 ]*dhcp-wait[	 ].*/	dhcp-wait $(NET_DHCP_WAIT)/' \
			-e 's/^[	 ]*ntp-server[	 ].*/	ntp-server $(NTP_SERVER)/' \
		-e 's/^[	 ]*ntp-timeout[	 ].*/	ntp-timeout $(NTP_TIMEOUT)/' \
		-e 's/^[	 ]*ntp-tries[	 ].*/	ntp-tries $(NTP_TRIES)/' \
			-e 's|^[	 ]*ntp-log[	 ].*|	ntp-log $(NTP_LOG)|' \
			-e 's/^[	 ]*esd-port[	 ].*/	esd-port $(ESD_PORT)/' \
		-e 's/^[	 ]*esd-rate[	 ].*/	esd-rate $(ESD_RATE)/' \
			-e 's|^[	 ]*esd-log[	 ].*|	esd-log $(ESD_LOG)|' \
			-e 's/^[	 ]*nfs-server[	 ].*/	nfs-server $(NFS_SERVER)/' \
		-e 's|^[	 ]*nfs-export[	 ].*|	nfs-export $(NFS_EXPORT)|' \
		-e "s|^[	 ]*nfs-device[	 ].*|	nfs-device $$device|" \
		root/etc/network/interfaces > $@

$(BUILD)/root/etc/ipserial.conf: Makefile root/etc/ipserial.conf $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@mode="$(IPSERIAL_MODE)"; \
	case "$$mode" in tcp|TCP|udp|UDP) ;; *) mode=tcp ;; esac; \
	sed -e "s/^[	 ]*mode[	 ]*=.*/mode=$$mode/" \
		-e "s/^[	 ]*port[	 ]*=.*/port=$(IPSERIAL_PORT)/" \
		root/etc/ipserial.conf > $@

$(BUILD)/root/etc/default/uart: Makefile $(UART_DEFAULTS) $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@cp $(UART_DEFAULTS) $@

$(BUILD)/root/etc/hosts: Makefile $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@printf '127.0.0.1\tlocalhost localhost.localdomain\n' > $@
	@printf '%s\t%s antler\n' '$(NET_LOCALIP)' '$(NET_HOSTNAME)' >> $@
	@printf '%s\tgateway router nameserver\n' '$(NET_GATEWAY)' >> $@
	@printf '192.168.10.116\thulk hulk.lan\n' >> $@
	@printf '10.0.2.15\tantler15\n10.0.2.16\tantler16\n10.0.2.17\tantler17\n10.0.2.2\temulator-gateway\n' >> $@
	@if [ -n '$(NET_EXTRA_HOST_NAME)' ] && [ -n '$(NET_EXTRA_HOST_IP)' ]; then \
		printf '%s\t%s\n' '$(NET_EXTRA_HOST_IP)' '$(NET_EXTRA_HOST_NAME)' >> $@; \
	fi

$(BUILD)/root/etc/resolv.conf: Makefile $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@printf '# Resolver defaults generated from the image network profile.\n' > $@
	@printf 'nameserver %s\n' '$(NET_DNSSERVER)' >> $@

$(BUILD)/root/etc/default/rcS: Makefile root/etc/default/rcS $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@if test "$(ENABLE_NETWORK)" = "1"; then \
		cp root/etc/default/rcS $@; \
	else \
		sed '/^# Start networking/,/^NETWORK_START=/d' \
			root/etc/default/rcS > $@; \
	fi

$(BUILD)/root/etc/default/sound: Makefile $(SOUND_DEFAULTS) $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@sed -e 's/^[	 ]*SOUND_RATE[	 ]*=.*/SOUND_RATE=$(SOUND_RATE)/' \
		-e 's/^[	 ]*SOUND_DRIVER[	 ]*=.*/SOUND_DRIVER=$(SOUND_DRIVER_FILE)/' \
		-e 's/^[	 ]*SOUND_SB_PORT[	 ]*=.*/SOUND_SB_PORT=$(SB_PORT)/' \
		-e 's/^[	 ]*SOUND_SB_IRQ[	 ]*=.*/SOUND_SB_IRQ=$(SB_IRQ)/' \
		-e 's/^[	 ]*SOUND_SB_DMA[	 ]*=.*/SOUND_SB_DMA=$(SB_DMA)/' \
		-e 's/^[	 ]*SOUND_DRIVER_MODE[	 ]*=.*/SOUND_DRIVER_MODE=$(if $(filter 1,$(SOUND_IRQ_AWARE)),interrupt,polling)/' \
		-e 's/^[	 ]*SOUND_OPTI_SB_MODE[	 ]*=.*/SOUND_OPTI_SB_MODE=$(SOUND_OPTI_SB_MODE)/' \
		-e 's/^[	 ]*SOUND_OPTI_SB_PORT[	 ]*=.*/SOUND_OPTI_SB_PORT=$(SOUND_OPTI_SB_PORT)/' \
		-e 's/^[	 ]*SOUND_OPTI_SB_IRQ[	 ]*=.*/SOUND_OPTI_SB_IRQ=$(SOUND_OPTI_SB_IRQ)/' \
		-e 's/^[	 ]*SOUND_OPTI_SB_DMA[	 ]*=.*/SOUND_OPTI_SB_DMA=$(SOUND_OPTI_SB_DMA)/' \
		-e 's/^[	 ]*SOUND_MAD16[	 ]*=.*/SOUND_MAD16=$(SOUND_OPTI_SB_MODE)/' \
		-e 's/^[	 ]*SOUND_MAD16_PORT[	 ]*=.*/SOUND_MAD16_PORT=$(SOUND_OPTI_SB_PORT)/' \
		-e 's/^[	 ]*SOUND_MAD16_IRQ[	 ]*=.*/SOUND_MAD16_IRQ=$(SOUND_OPTI_SB_IRQ)/' \
		-e 's/^[	 ]*SOUND_MAD16_DMA[	 ]*=.*/SOUND_MAD16_DMA=$(SOUND_OPTI_SB_DMA)/' \
		"$(SOUND_DEFAULTS)" > $@

$(BUILD)/root/etc/default/root: Makefile root/etc/default/root $(BUILD_CONFIG)
	@mkdir -p $(dir $@)
	@if test "$(ENABLE_NETWORK)" = "1"; then \
		sed -e 's|^ROOT_DEVICE=.*|ROOT_DEVICE=$(ROOT_DEVICE)|' \
			-e 's|^ROOT_FSTYPE=.*|ROOT_FSTYPE=$(ROOT_FS_TYPE)|' \
			-e 's|^ROOT_FLAGS=.*|ROOT_FLAGS=$(ROOT_FLAGS)|' \
			root/etc/default/root > $@; \
	else \
		sed '/^# NFS can also be root/,/^#   ROOT_FLAGS=rw/d' \
			root/etc/default/root \
		| sed -e 's|^ROOT_DEVICE=.*|ROOT_DEVICE=$(ROOT_DEVICE)|' \
			-e 's|^ROOT_FSTYPE=.*|ROOT_FSTYPE=$(ROOT_FS_TYPE)|' \
			-e 's|^ROOT_FLAGS=.*|ROOT_FLAGS=$(ROOT_FLAGS)|' > $@; \
	fi

$(ARCHIVE): $(MKBOOTAR) $(NATIVE_BINS) $(ROOT_ARCHIVE_FILES) $(ROOT_GENERATED_FILES) $(ARCHIVE_EXTRA_DEPS)
	$(MKBOOTAR) $@ \
		sbin/init=$(INIT_BIN) \
		$(NATIVE_ARCHIVE_ARGS) \
		$(ANX2_SERVICE_ARCHIVE_ARGS) \
		$(ROOT_ARCHIVE_ARGS) \
		$(ARCHIVE_EXTRA_ARGS)

clean:
	rm -rf $(BUILD)
