#
# Makefile - kboot main Makefile
#
# Written 2005-2007 by Werner Almesberger
#


include VERSIONS
ifeq (config/answers,$(wildcard config/answers))
include config/answers
endif


# ----- Local configuration data ----------------------------------------------


LOCAL_KERNEL_CONFIG=$(PWD)/config/kernel-config
LOCAL_HOSTS=$(PWD)/config/hosts
LOCAL_PASSWD=$(PWD)/config/passwd
LOCAL_KBOOT_CONF=$(PWD)/config/kboot.conf
LOCAL_OPENSSH_RSA=$(PWD)/config/ssh_host_rsa_key
LOCAL_OPENSSH_DSA=$(PWD)/config/ssh_host_dsa_key
LOCAL_DROPBEAR_RSA=$(PWD)/config/dropbear_rsa_host_key
LOCAL_DROPBEAR_DSS=$(PWD)/config/dropbear_dss_host_key
LOCAL_AUTHORIZED_KEYS=$(PWD)/config/authorized_keys
KBOOT_MESSAGE=$(PWD)/config/message


# ----- Naming conversions ----------------------------------------------------


KERNEL_DIR=linux-$(KERNEL_VERSION)
KERNEL_PACKAGE=linux-$(KERNEL_VERSION).tar.bz2
KERNEL_URL=http://ftp.kernel.org/pub/linux/kernel/v2.6/$(KERNEL_PACKAGE)

GCC_DIR=gcc-$(GCC_VERSION)
GCC_PACKAGE=gcc-core-$(GCC_VERSION).tar.bz2
GCC_URL=http://ftp.gnu.org/gnu/gcc/gcc-$(GCC_VERSION)/$(GCC_PACKAGE)

BINUTILS_DIR=binutils-$(BINUTILS_VERSION)
BINUTILS_PACKAGE=binutils-$(BINUTILS_VERSION).tar.bz2
BINUTILS_URL= \
  http://ftp.gnu.org/gnu/binutils/binutils-$(BINUTILS_VERSION).tar.bz2

UCLIBC_DIR=uClibc-$(UCLIBC_VERSION)
UCLIBC_PACKAGE=uClibc-$(UCLIBC_VERSION).tar.bz2
UCLIBC_URL=http://www.uclibc.org/downloads/$(UCLIBC_PACKAGE)

BUSYBOX_DIR=busybox-$(BUSYBOX_VERSION)
BUSYBOX_PACKAGE=busybox-$(BUSYBOX_VERSION).tar.bz2
BUSYBOX_URL=http://www.busybox.net/downloads/$(BUSYBOX_PACKAGE)

UDEV_DIR=udev-$(UDEV_VERSION)
UDEV_PACKAGE=udev-$(UDEV_VERSION).tar.bz2
UDEV_URL=http://www.kernel.org/pub/linux/utils/kernel/hotplug/$(UDEV_PACKAGE)

KEXEC_TOOLS_PACKAGE=kexec-tools-$(KEXEC_TOOLS_VERSION).tar.gz
KEXEC_TOOLS_DIR=kexec-tools-$(KEXEC_TOOLS_VERSION)
KEXEC_TOOLS_URL= \
  http://www.xmission.com/~ebiederm/files/kexec/$(KEXEC_TOOLS_PACKAGE)

DROPBEAR_PACKAGE=dropbear-$(DROPBEAR_VERSION).tar.gz
DROPBEAR_DIR=dropbear-$(DROPBEAR_VERSION)
DROPBEAR_URL=http://matt.ucc.asn.au/dropbear/releases/$(DROPBEAR_PACKAGE)

KBD_PACKAGE=kbd-$(KBD_VERSION).tar.gz
KBD_DIR=kbd-$(KBD_VERSION)
KBD_URL=ftp://ftp.win.tue.nl/pub/linux-local/utils/kbd/$(KBD_PACKAGE)

LILO_PACKAGE=lilo-$(LILO_VERSION).src.tar.gz
LILO_DIR=lilo-$(LILO_VERSION)
LILO_URL=http://home.san.rr.com/johninsd/pub/linux/lilo/$(LILO_PACKAGE)

DL=$(if $(wildcard ../dl/.),../dl,dl)


# ----- Macros ----------------------------------------------------------------


define edit_config
	scripts/edit-config $(1)
endef


# ----- Files to include in distribution --------------------------------------


FILES=VERSIONS CHANGES README TODO COPYING.GPL \
      Makefile \
      scripts/kboot scripts/udhcpc.script \
      scripts/common-all scripts/common-config \
      scripts/find-features scripts/update-fstab \
      scripts/find-shlibs scripts/edit-config \
      utils/Makefile utils/readline.c utils/getctty.c utils/fsbyname.c \
      config/README \
      patches/README \
      patches/kexec-tools-1.101-fix-real-mode-entry-vivek.patch \
      patches/kbd-bkeymap.patch patches/busybox-noshadow.patch \
      patches/busybox-htons.patch


# ----- General settings ------------------------------------------------------


.PHONY:	all reconfig config download packages keymaps
.PHONY:	try reset clean spotless dist upload

all:	kboot-root.cpio.gz

using_uclibc_cross=PATH=$(PWD)/build/bin:$$PATH
using_uclibc=PATH=$(PWD)/build/bin:$(PWD)/build/uclibc/bin:$$PATH
using_safe_gcc=PATH=$(PWD)/build/bin:$(PWD)/build/host/bin:$$PATH


# ----- (Re)Configuration -----------------------------------------------------


reconfig:
	rm -f config/answers
	make config

config:
	scripts/update-fstab
	scripts/find-features


# ----- Download 3rd party packages -------------------------------------------


download: \
	$(DL)/$(KERNEL_PACKAGE).ok \
	  $(DL)/$(GCC_PACKAGE).ok \
	  $(DL)/$(BINUTILS_PACKAGE).ok \
	  $(DL)/$(UCLIBC_PACKAGE).ok \
	  $(DL)/$(BUSYBOX_PACKAGE).ok \
	  $(DL)/$(UDEV_PACKAGE).ok \
	  $(DL)/$(KEXEC_TOOLS_PACKAGE).ok \
	  $(DL)/$(DROPBEAR_PACKAGE).ok \
	  $(DL)/$(KBD_PACKAGE).ok \
#	  $(DL)/$(LILO_PACKAGE).ok

packages:
	@echo $(KERNEL_PACKAGE)
	@echo $(GCC_PACKAGE)
	@echo $(BINUTILS_PACKAGE)
	@echo $(UCLIBC_PACKAGE)
	@echo $(BUSYBOX_PACKAGE)
	@echo $(UDEV_PACKAGE)
	@echo $(KEXEC_TOOLS_PACKAGE)
	@echo $(DROPBEAR_PACKAGE)
	@echo $(KBD_PACKAGE)
#	@echo $(LILO_PACKAGE)

$(DL)/$(KERNEL_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(KERNEL_PACKAGE) $(KERNEL_URL)
	touch $@

$(DL)/$(LILO_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(LILO_PACKAGE) $(LILO_URL)
	touch $@

$(DL)/$(GCC_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(GCC_PACKAGE) $(GCC_URL)
	touch $@

$(DL)/$(BINUTILS_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(BINUTILS_PACKAGE) $(BINUTILS_URL)
	touch $@

$(DL)/$(UCLIBC_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(UCLIBC_PACKAGE) $(UCLIBC_URL)
	touch $@

$(DL)/$(BUSYBOX_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(BUSYBOX_PACKAGE) $(BUSYBOX_URL)
	touch $@

$(DL)/$(UDEV_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(UDEV_PACKAGE) $(UDEV_URL)
	touch $@

$(DL)/$(DROPBEAR_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(DROPBEAR_PACKAGE) $(DROPBEAR_URL)
	touch $@

$(DL)/$(KEXEC_TOOLS_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(KEXEC_TOOLS_PACKAGE) $(KEXEC_TOOLS_URL)
	touch $@

$(DL)/$(KBD_PACKAGE).ok:
	mkdir -p dl
	wget -c -O $(DL)/$(KBD_PACKAGE) $(KBD_URL)
	touch $@


# ----- The root file system --------------------------------------------------


root/etc/kboot-features: \
	  scripts/find-features root/etc/fstab # ...
	scripts/find-features make
	touch $@	# may be cached

root/etc/fstab: \
	  scripts/update-fstab # ...
	scripts/update-fstab
	touch $@	# may be cached

root:	root/etc/kboot-features root/etc/fstab \
	root-meta/installed/uclibc root-meta/installed/busybox \
	  root-meta/installed/udev \
	  $(if $(subst false,,$(ssh_client)),root-meta/installed/dropbear) \
	  $(if $(subst false,,$(ssh_server)),root-meta/installed/dropbear) \
	  $(if $(subst false,,$(ssh_generate_keys)),\
	    $(DROPBEAR_DIR)-host/.kboot-built) \
	  $(if $(subst false,,$(ssh_convert_keys)),\
	    $(DROPBEAR_DIR)-host/.kboot-built) \
	  root-meta/installed/kexec-tools \
	  Makefile scripts/kboot scripts/common-all \
	  $(if $(subst false,,$(use_dhcp)),scripts/udhcpc.script) \
	  utils/uclibc-readline utils/uclibc-getctty utils/uclibc-fsbyname \
	  $(if $(wildcard $(LOCAL_HOSTS)),$(LOCAL_HOSTS)) \
	  $(if $(wildcard $(LOCAL_PASSWD)),$(LOCAL_PASSWD)) \
	  $(if $(wildcard $(LOCAL_KBOOT_CONF)),$(LOCAL_KBOOT_CONF)) \
	  $(if $(wildcard $(KBOOT_MESSAGE)),$(KBOOT_MESSAGE)) \
	  $(if $(wildcard $(LOCAL_OPENSSH_RSA)),$(LOCAL_OPENSSH_RSA)) \
	  $(if $(wildcard $(LOCAL_OPENSSH_DSA)),$(LOCAL_OPENSSH_DSA)) \
	  $(if $(wildcard $(LOCAL_DROPBEAR_RSA)),$(LOCAL_DROPBEAR_RSA)) \
	  $(if $(wildcard $(LOCAL_DROPBEAR_DSS)),$(LOCAL_DROPBEAR_DSS)) \
	  $(if $(wildcard $(LOCAL_AUTHORIZED_KEYS)),$(LOCAL_AUTHORIZED_KEYS)) \
	  $(if $(wildcard config/*.bkeymap),config/*.bkeymap)
	rm -f etc/root/{hosts,passwd,kboot.conf,message}
	rm -rf root/tmp root/dev
	mkdir -p root/etc root/tmp root/proc root/dev root/sys
	mkdir -p root/mnt/tmp root/mnt/root
	[ -e root/dev/console ] || mknod root/dev/console c 5 1
	[ -e root/dev/null ] || mknod root/dev/null c 1 3
	[ -e root/dev/tty1 ] || mknod root/dev/tty1 c 4 1
	[ ! -r "$(LOCAL_HOSTS)" ] || cp "$(LOCAL_HOSTS)" root/etc/
	if [ -r "$(LOCAL_PASSWD)" ]; then \
	    cp "$(LOCAL_PASSWD)" root/etc/; \
	else \
	    echo 'kboot:*:0:0:kboot user:/:/sbin/kboot' >root/etc/passwd; \
	fi
	[ ! -r "$(LOCAL_KBOOT_CONF)" ] || cp "$(LOCAL_KBOOT_CONF)" root/etc/
	[ ! -r "$(KBOOT_MESSAGE)" ] || cp "$(KBOOT_MESSAGE)" root/etc/
	cp scripts/kboot scripts/common-all root/sbin/	# stupid place ...
    ifeq ($(use_dhcp),true)
	cp scripts/udhcpc.script root/sbin/
    endif
    ifeq ($(ssh_generate_keys),true)
	[ -r $(LOCAL_DROPBEAR_RSA) ] || \
	  $(DROPBEAR_DIR)-host/dropbearkey -t rsa -f $(LOCAL_DROPBEAR_RSA)
	[ -r $(LOCAL_DROPBEAR_DSS) ] || \
	  $(DROPBEAR_DIR)-host/dropbearkey -t dss -f $(LOCAL_DROPBEAR_DSS)
    else
      ifeq ($(ssh_convert_keys),true)
	[ ! -r $(LOCAL_OPENSSH_RSA) -o -r $(LOCAL_DROPBEAR_RSA) ] || \
	    $(DROPBEAR_DIR)-host/dropbearconvert openssh dropbear \
	      $(LOCAL_OPENSSH_RSA) $(LOCAL_DROPBEAR_RSA)
	[ ! -r $(LOCAL_OPENSSH_DSA) -o -r $(LOCAL_DROPBEAR_DSS) ] || \
	    $(DROPBEAR_DIR)-host/dropbearconvert openssh dropbear \
	      $(LOCAL_OPENSSH_DSA) $(LOCAL_DROPBEAR_DSS)
      endif
    endif
	if [ -r $(LOCAL_DROPBEAR_RSA) ]; then \
	    mkdir -p root/etc/dropbear; \
	    cp $(LOCAL_DROPBEAR_RSA) root/etc/dropbear/; \
	fi
	if [ -r $(LOCAL_DROPBEAR_DSS) ]; then \
	    mkdir -p root/etc/dropbear; \
	    cp $(LOCAL_DROPBEAR_DSS) root/etc/dropbear/; \
	fi
	if [ -r $(LOCAL_AUTHORIZED_KEYS) ]; then \
	    mkdir -p root/.ssh; \
	    cp $(LOCAL_AUTHORIZED_KEYS) root/.ssh/; \
	fi
    ifeq ($(ssh_server),true)
	echo /sbin/kboot >root/etc/shells
	touch root/etc/group
	mkdir -p root/dev/pts root/var/run
    endif
	rm -f root/etc/default.bkeymap
	if [ "`echo config/*.bkeymap`" != 'config/*.bkeymap' ]; then \
	    if [ ! -r "`echo config/*.bkeymap`" ]; then \
		echo "please put only one keymap into config/" 1>&2; \
		exit 1; \
	    fi; \
	    cp config/*.bkeymap root/etc/default.bkeymap; \
	fi
	install -s utils/uclibc-readline root/bin/readline
	install -s utils/uclibc-getctty root/sbin/getctty
	install -s utils/uclibc-fsbyname root/sbin/fsbyname
	ln -sf /sbin/kboot root/init

kboot-root.cpio.gz: \
	  root
	rm -f kboot-root.cpio.gz # make sure we get the right permissions
	(umask 077; cd root && find . | cpio -o -H newc | \
	  gzip >../kboot-root.cpio.gz; ) || \
	  { rm -f kboot-root.cpio.gz; exit 1; }


# ----- Build the kernel ------------------------------------------------------


$(KERNEL_DIR)/.kboot-extracted: \
	  $(DL)/$(KERNEL_PACKAGE).ok
	rm -f $@ $(KERNEL_DIR)/.kboot-configured $(KERNEL_DIR)/.kboot-built
	tar xfj $(DL)/$(KERNEL_PACKAGE)
	touch $@

$(KERNEL_DIR)/.kboot-configured: \
	  $(KERNEL_DIR)/.kboot-extracted $(LOCAL_KERNEL_CONFIG)
	rm -f $@ $(KERNEL_DIR)/.kboot-built
	cp $(LOCAL_KERNEL_CONFIG) $(KERNEL_DIR)/.config
	$(edit_config) $(KERNEL_DIR)/.config \
	  CONFIG_KEXEC=y \
	  CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_INITRD=y \
	  +CONFIG_BLK_DEV_RAM_COUNT=1 \
	  +CONFIG_BLK_DEV_RAM_SIZE=4096
	make -C $(KERNEL_DIR) oldconfig include/asm
	touch $@

$(KERNEL_DIR)/.kboot-built: \
	  $(KERNEL_DIR)/.kboot-configured
	rm -f $@
	make -C $(KERNEL_DIR)
	touch $@


# ----- Build binutils --------------------------------------------------------


$(BINUTILS_DIR)/.kboot-extracted: \
	  $(DL)/$(BINUTILS_PACKAGE).ok
	rm -f $@ $(BINUTILS_DIR)/.kboot-configured \
	  $(BINUTILS_DIR)/.kboot-built build/installed/binutils
	tar xfj $(DL)/$(BINUTILS_PACKAGE)
	touch $@

$(BINUTILS_DIR)/.kboot-configured: \
	  $(BINUTILS_DIR)/.kboot-extracted
	rm -f $@ $(BINUTILS_DIR)/.kboot-built build/installed/binutils
	( cd $(BINUTILS_DIR) && ./configure --prefix=$(PWD)/build; )
	touch $@

$(BINUTILS_DIR)/.kboot-built: \
	  $(BINUTILS_DIR)/.kboot-configured
	rm -f $@ build/installed/binutils
	make -C $(BINUTILS_DIR)
	touch $@

build/installed/binutils: \
	  $(BINUTILS_DIR)/.kboot-built
	rm -f $@
	mkdir -p build/installed
	make -C $(BINUTILS_DIR) install
	( cd build/bin && \
	  for n in *; do \
	    if [ "x$${n#*-}" = "x$$n" ]; then \
	      ln -sf $$n host-$$n || exit 1; \
	      ln -sf $$n uclibc-$$n || exit 1; \
	    fi; \
	  done; )
	touch $@


# ----- Build gcc (using host libc, typically glibc) --------------------------


$(GCC_DIR)/.kboot-extracted: \
	  $(DL)/$(GCC_PACKAGE).ok
	rm -f $@ \
	  $(GCC_DIR)-host/.kboot-configured $(GCC_DIR)-host/.kboot-built \
	  build/installed/gcc-host $(GCC_DIR)-uclibc/.kboot-configured \
	  $(GCC_DIR)-uclibc/.kboot-built build/installed/gcc-uclibc
	tar xfj $(DL)/$(GCC_PACKAGE)
	touch $@

$(GCC_DIR)-host/.kboot-configured: \
	  $(GCC_DIR)/.kboot-extracted build/installed/binutils
	rm -f $@ $(GCC_DIR)-host/.kboot-built build/installed/gcc-host
	mkdir -p $(GCC_DIR)-host
	mkdir -p $(PWD)/build/usr/include
	( cd $(GCC_DIR)-host && \
	  ../$(GCC_DIR)/configure \
	  --prefix=$(PWD)/build/host \
	  --enable-languages=c; )
	touch $@

$(GCC_DIR)-host/.kboot-built: \
	  $(GCC_DIR)-host/.kboot-configured
	rm -f $@ build/installed/gcc-host
	make -C $(GCC_DIR)-host
	touch $@

build/installed/gcc-host: \
	  $(GCC_DIR)-host/.kboot-built
	rm -f $@
	mkdir -p build/installed
	make -C $(GCC_DIR)-host install
	(cd build/bin && \
	  for n in gcc cpp; do ln -sf ../host/bin/$$n host-$$n || exit 1; \
	    done; )
	touch $@


# ----- Build gcc (using uClibc) ----------------------------------------------


$(GCC_DIR)-uclibc/.kboot-configured: \
	  $(GCC_DIR)/.kboot-extracted build/installed/binutils
	rm -f $@ $(GCC_DIR)-uclibc/.kboot-built build/installed/gcc-uclibc
	mkdir -p $(GCC_DIR)-uclibc
	( cd $(GCC_DIR)-uclibc && \
	  ../$(GCC_DIR)/configure \
	  --with-sysroot=$(PWD)/build \
	  --prefix=$(PWD)/build/uclibc \
	  --enable-languages=c; )
	touch $@

$(GCC_DIR)-uclibc/.kboot-built: \
	  $(GCC_DIR)-uclibc/.kboot-configured
	rm -f $@ build/installed/gcc-uclibc
	make -C $(GCC_DIR)-uclibc
	touch $@

build/installed/gcc-uclibc: \
	  $(GCC_DIR)-uclibc/.kboot-built
	rm -f $@
	mkdir -p build/installed
	make -C $(GCC_DIR)-uclibc install
	# @@@ ugly hack. I wonder how to make gcc pick of the right linker ...
	perl -pi -e 's|/lib/ld-linux.so.\d+|/lib/ld-uClibc.so.0|g' \
	  build/uclibc/lib/gcc/*/$(GCC_VERSION)/specs
	(cd build/bin && \
	  for n in gcc cpp; do ln -sf ../uclibc/bin/$$n uclibc-$$n || exit 1; \
	  done; )
	touch $@


# ----- Build uClibc ----------------------------------------------------------


$(UCLIBC_DIR)/.kboot-extracted: \
	  $(DL)/$(UCLIBC_PACKAGE).ok
	rm -f $@ $(UCLIBC_DIR)/.kboot-configured $(UCLIBC_DIR)/.kboot-built \
	  build/installed/uclibc root-meta/installed/uclibc
	tar xfj $(DL)/$(UCLIBC_PACKAGE)
	touch $@

$(UCLIBC_DIR)/.kboot-configured: \
	  $(UCLIBC_DIR)/.kboot-extracted $(KERNEL_DIR)/.kboot-built
	rm -f $@ $(UCLIBC_DIR)/.kboot-built build/installed/uclibc
	make -C $(UCLIBC_DIR) defconfig
	$(edit_config) $(UCLIBC_DIR)/.config \
	  'KERNEL_SOURCE="$(PWD)/$(KERNEL_DIR)"' \
	  'SHARED_LIB_LOADER_PREFIX="/lib"' \
	  'RUNTIME_PREFIX="/"' \
	  'DEVEL_PREFIX="/usr"'
    ifeq ($(nfs_client),true)
	$(edit_config) $(UCLIBC_DIR)/.config \
	  UCLIBC_HAS_RPC=y UCLIBC_HAS_FULL_RPC=n
    endif
	make -C $(UCLIBC_DIR) oldconfig 
	touch $@

$(UCLIBC_DIR)/.kboot-built: \
	  $(UCLIBC_DIR)/.kboot-configured build/installed/gcc-host
	rm -f $@ build/installed/uclibc root-meta/installed/uclibc
	$(using_safe_gcc) make -C $(UCLIBC_DIR)
	touch $@

build/installed/uclibc: \
	  $(UCLIBC_DIR)/.kboot-built
	rm -f $@
	mkdir -p build/installed
	make -C $(UCLIBC_DIR) PREFIX=$(PWD)/build install_runtime
	make -C $(UCLIBC_DIR) PREFIX=$(PWD)/build install_dev
	touch $@

root-meta/installed/uclibc: \
	  $(UCLIBC_DIR)/.kboot-built
	rm -f $@
	mkdir -p root root-meta/installed
	make -C $(UCLIBC_DIR) PREFIX=$(PWD)/root install_runtime
	rm -f root/lib/lib{dl,m,nsl,pthread,rt}[.-]*
	touch $@


# ----- Build BusyBox ---------------------------------------------------------


$(BUSYBOX_DIR)/.kboot-extracted: \
	  $(DL)/$(BUSYBOX_PACKAGE).ok
	rm -f $@ $(BUSYBOX_DIR)/.kboot-configured $(BUSYBOX_DIR)/.kboot-built \
	  root-meta/installed/busybox
	tar xfj $(DL)/$(BUSYBOX_PACKAGE)
	patch -d $(BUSYBOX_DIR) -p1 -s <patches/busybox-noshadow.patch
	patch -d $(BUSYBOX_DIR) -p1 -s <patches/busybox-htons.patch
	touch $@

$(BUSYBOX_DIR)/.kboot-configured: \
	  $(BUSYBOX_DIR)/.kboot-extracted build/installed/uclibc
	rm -f $@ $(BUSYBOX_DIR)/.kboot-built root-meta/installed/busybox
	make -C $(BUSYBOX_DIR) allnoconfig
	# General Configuration
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_FEATURE_VERBOSE_USAGE=y \
	  CONFIG_FEATURE_DEVPTS=y
	# Installation Options
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  'CONFIG_PREFIX="$(PWD)/root"'
	# Busybox Library Tuning
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_MD5_SIZE_VS_SPEED=3
	# Archival Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_BUNZIP2=y \
	  CONFIG_GUNZIP=y \
	  CONFIG_GZIP=y \
	  CONFIG_TAR=y CONFIG_FEATURE_TAR_CREATE=y CONFIG_FEATURE_TAR_BZIP2=y \
	  CONFIG_FEATURE_TAR_GZIP=y CONFIG_FEATURE_TAR_OLDGNU_COMPATIBILITY=y \
	  CONFIG_FEATURE_TAR_GNU_EXTENSIONS=y \
	  CONFIG_UNZIP=y
	# Coreutils
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_CAT=y CONFIG_CHROOT=y CONFIG_CP=y \
	  CONFIG_DATE=y \
	  CONFIG_DD=y CONFIG_DF=y \
	  CONFIG_DU=y CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K=y \
	  CONFIG_ECHO=y CONFIG_FEATURE_FANCY_ECHO=y \
	  CONFIG_ENV=y \
	  CONFIG_EXPR=y \
	  CONFIG_HEAD=y \
	  CONFIG_LN=y \
	  CONFIG_LS=y CONFIG_FEATURE_LS_FILETYPES=y \
	  CONFIG_FEATURE_LS_FOLLOWLINKS=y CONFIG_FEATURE_LS_RECURSIVE=y \
	  CONFIG_FEATURE_LS_SORTFILES=y CONFIG_FEATURE_LS_TIMESTAMPS=y \
	  CONFIG_FEATURE_LS_USERNAME=y \
	  CONFIG_MD5SUM=y CONFIG_MKDIR=y CONFIG_MKNOD=y CONFIG_MV=y \
	  CONFIG_RM=y CONFIG_RMDIR=y \
	  CONFIG_SHA1SUM=y CONFIG_SORT=y CONFIG_SYNC=y \
	  CONFIG_TAIL=y CONFIG_FEATURE_FANCY_TAIL=y \
	  CONFIG_TOUCH=y CONFIG_TRUE=y \
	  CONFIG_UNAME=y \
	  CONFIG_FEATURE_PRESERVE_HARDLINKS=y \
	  CONFIG_FEATURE_HUMAN_READABLE=y
#	CONFIG_EXPR=n CONFIG_FALSE=n CONFIG_TRUE=n
	# Console Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_LOADKMAP=y
	# Debian Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_WHICH=y
	# Init Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_HALT=y
# 	CONFIG_HALT=n (reboot)
	# Linux System Utilities
    ifeq ($(nfs_client),true)
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_FEATURE_MOUNT_NFS=y
    endif
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_DMESG=y \
	  CONFIG_HEXDUMP=y \
	  CONFIG_MORE=y CONFIG_FEATURE_USE_TERMIOS=y \
	  CONFIG_MOUNT=y \
	  CONFIG_SWITCH_ROOT=y \
	  CONFIG_UMOUNT=y \
	  CONFIG_FEATURE_MOUNT_LOOP=y
	# Networking Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_IFCONFIG=y CONFIG_FEATURE_IFCONFIG_STATUS=y \
	  CONFIG_PING=y CONFIG_FEATURE_FANCY_PING=y \
	  CONFIG_ROUTE=y \
	  CONFIG_TFTP=y CONFIG_FEATURE_TFTP_GET=y \
	  CONFIG_WGET=y CONFIG_FEATURE_WGET_STATUSBAR=y \
	  CONFIG_FEATURE_WGET_AUTHENTICATION=y
    ifeq ($(use_dhcp),true)
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_APP_UDHCPC=y
    endif
	# Process Utilities
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_FREE=y
	# Shells
	$(edit_config) $(BUSYBOX_DIR)/.config \
	  CONFIG_FEATURE_SH_IS_ASH=y \
	  CONFIG_FEATURE_SH_IS_NONE=n \
	  CONFIG_ASH=y CONFIG_ASH_JOB_CONTROL=y \
	  CONFIG_ASH_OPTIMIZE_FOR_SIZE=y CONFIG_ASH_EXPAND_PRMT=y \
	  CONFIG_FEATURE_COMMAND_EDITING=y \
	  CONFIG_FEATURE_COMMAND_HISTORY=15 \
	  CONFIG_FEATURE_COMMAND_TAB_COMPLETION=y \
	  CONFIG_FEATURE_SH_FANCY_PROMPT=y
	make -C $(BUSYBOX_DIR) oldconfig
	touch $@

$(BUSYBOX_DIR)/.kboot-built: \
	  $(BUSYBOX_DIR)/.kboot-configured build/installed/gcc-uclibc
	rm -f $@ root-meta/installed/busybox
	$(using_uclibc_cross) make -C $(BUSYBOX_DIR) CROSS_COMPILE=uclibc-
	touch $@

root-meta/installed/busybox: \
	  $(BUSYBOX_DIR)/.kboot-built root-meta/installed/uclibc
	rm -f $@
	mkdir -p root root-meta/installed
	$(using_uclibc_cross) make -C $(BUSYBOX_DIR) install \
	  CROSS_COMPILE=uclibc-
	touch $@


# ----- Build udev -----------------------------------------------------------


$(UDEV_DIR)/.kboot-extracted: \
	  $(DL)/$(UDEV_PACKAGE).ok
	rm -f $@ $(UDEV_DIR)/.kboot-built root-meta/udev/installed
	tar xfj $(DL)/$(UDEV_PACKAGE)
	touch $@

$(UDEV_DIR)/.kboot-built: \
	  $(UDEV_DIR)/.kboot-extracted $(KERNEL_DIR)/.kboot-built \
	  build/installed/gcc-uclibc
	rm -f $@ root-meta/udev/installed
	$(using_uclibc_cross) make -C $(UDEV_DIR) CROSS_COMPILE=uclibc- \
	  prefix=$(PWD)/root \
	  KERNEL_DIR=$(PWD)/$(KERNEL_DIR) \
	  USE_KLIBC=false USE_LOG=false
	touch $@

root-meta/installed/udev: \
	  $(UDEV_DIR)/.kboot-built build/installed/gcc-uclibc \
	  root-meta/installed/uclibc
	rm -f $@
	mkdir -p root root-meta/installed
	$(using_uclibc_cross) make -C $(UDEV_DIR) CROSS_COMPILE=uclibc- \
	  DESTDIR=$(PWD)/root V=true install
	cp $(UDEV_DIR)/udevstart root/sbin/
	rm -f root/usr/bin/udev{test,info}
	rm -f root/usr/sbin/udev{monitor,info}
	rm -f root/sbin/udevcontrol
	rm -rf root/usr/share  # man pages
	strip root/sbin/udev*
	touch $@


# ----- Build Dropbear SSH (using host libc, typically glibc) -----------------

#
# We really only care about the key generator and converter
#

$(DROPBEAR_DIR)-host/.kboot-extracted: \
	  $(DL)/$(DROPBEAR_PACKAGE).ok
	rm -f $@ $(DROPBEAR_DIR)-host/.kboot-configured \
	  $(DROPBEAR_DIR)-host/.kboot-built
	# don't use --strip-components et al. for compatibility with older tar
	tar xfz $(DL)/$(DROPBEAR_PACKAGE)
	mv $(DROPBEAR_DIR) $(DROPBEAR_DIR)-host
	touch $@

$(DROPBEAR_DIR)-host/.kboot-configured: \
	  $(DROPBEAR_DIR)-host/.kboot-extracted
	rm -f $@ $(DROPBEAR_DIR)-host/.kboot-built
	( cd $(DROPBEAR_DIR)-host && \
	  ./configure --disable-zlib --disable-syslog; )
	touch $@

$(DROPBEAR_DIR)-host/.kboot-built: \
	  $(DROPBEAR_DIR)-host/.kboot-configured
	rm -f $@
	# dropbear won't build if we don't select client or server
	make -C $(DROPBEAR_DIR)-host \
	  PROGRAMS="dbclient dropbearkey dropbearconvert"
	touch $@


# ----- Build Dropbear SSH (using uClibc) -------------------------------------


$(DROPBEAR_DIR)-uclibc/.kboot-extracted: \
	  $(DL)/$(DROPBEAR_PACKAGE).ok
	rm -f $@ $(DROPBEAR_DIR)-uclibc/.kboot-configured
	rm -f $(DROPBEAR_DIR)-uclibc/.kboot-built root-meta/installed/dropbear
	# don't use --strip-components et al. for compatibility with older tar
	tar xfz $(DL)/$(DROPBEAR_PACKAGE)
	mv $(DROPBEAR_DIR) $(DROPBEAR_DIR)-uclibc
	touch $@

$(DROPBEAR_DIR)-uclibc/.kboot-configured: \
	  $(DROPBEAR_DIR)-uclibc/.kboot-extracted build/installed/gcc-uclibc
	rm -f $@ $(DROPBEAR_DIR)-uclibc/.kboot-built
	rm -f root-meta/installed/dropbear
	( cd $(DROPBEAR_DIR)-uclibc && \
	  $(using_uclibc) ./configure --host=`uname -m` \
	  --prefix=$(PWD)/root --disable-zlib --disable-syslog \
	  --disable-lastlog --disable-utmp --disable-utmpx --disable-wtmp \
	  --disable-wtmpx; )
	perl -pi -e 's/#define.ENABLE_X11FWD/#undef ENABLE_X11FWD/' \
	  $(DROPBEAR_DIR)-uclibc/options.h
	touch $@

DROPBEAR_PROGRAMS :=
ifeq ($(ssh_client),true)
DROPBEAR_PROGRAMS += dbclient
endif
ifeq ($(ssh_server),true)
DROPBEAR_PROGRAMS += dropbear
endif
ifeq ($(ssh_update_keys),true)
DROPBEAR_PROGRAMS += dropbearconvert
endif

$(DROPBEAR_DIR)-uclibc/.kboot-built: \
	  $(DROPBEAR_DIR)-uclibc/.kboot-configured build/installed/gcc-uclibc
	rm -f $@ root-meta/installed/dropbear
	$(using_uclibc) make -C $(DROPBEAR_DIR)-uclibc \
	  PROGRAMS="$(DROPBEAR_PROGRAMS)" MULTI=1
	touch $@

root-meta/installed/dropbear: \
	  $(DROPBEAR_DIR)-uclibc/.kboot-built
	rm -f $@
	mkdir -p root/bin root/sbin root-meta/installed
	install -s $(DROPBEAR_DIR)-uclibc/dropbearmulti root/bin
    ifeq ($(ssh_client),true)
	ln -sf /bin/dropbearmulti root/bin/ssh
    endif
    ifeq ($(ssh_server),true)
	ln -sf /bin/dropbearmulti root/sbin/dropbear
    endif
    ifeq ($(ssh_update_keys),true)
	ln -sf /bin/dropbearmulti root/bin/dropbearconvert
    endif
	touch $@


# ----- Build the kexec tools -------------------------------------------------


$(KEXEC_TOOLS_DIR)/.kboot-extracted: \
	  $(DL)/$(KEXEC_TOOLS_PACKAGE).ok
	rm -f $@ $(KEXEC_TOOLS_DIR)/.kboot-configured \
	  $(KEXEC_TOOLS_DIR)/.kboot-built root-meta/installed/kexec-tools
	tar xfz $(DL)/$(KEXEC_TOOLS_PACKAGE)
	rm -f kexec-tools-$(KEXEC_TOOLS_VERSION).spec
	patch -d $(KEXEC_TOOLS_DIR) -p1 -s \
	  <patches/kexec-tools-1.101-fix-real-mode-entry-vivek.patch
	touch $@

$(KEXEC_TOOLS_DIR)/.kboot-configured: \
	  $(KEXEC_TOOLS_DIR)/.kboot-extracted build/installed/gcc-uclibc
	rm -f $@ $(KEXEC_TOOLS_DIR)/.kboot-built \
	  root-meta/installed/kexec-tools
	( cd $(KEXEC_TOOLS_DIR) && \
	  $(using_uclibc_cross) ./configure --build=`uname -m`-linux-uclibc \
	  --host=`uname -m` --prefix=$(PWD)/root CC=uclibc-gcc; )
	touch $@

$(KEXEC_TOOLS_DIR)/.kboot-built: \
	  $(KEXEC_TOOLS_DIR)/.kboot-configured build/installed/gcc-uclibc
	rm -f $@ root-meta/installed/kexec-tools
	$(using_uclibc_cross) make -C $(KEXEC_TOOLS_DIR) CC=uclibc-gcc
	touch $@

root-meta/installed/kexec-tools: \
	  $(KEXEC_TOOLS_DIR)/.kboot-built
	rm -f $@
	mkdir -p root root-meta/installed
	$(using_uclibc_cross) make -C $(KEXEC_TOOLS_DIR) install
	strip root/sbin/kexec
	rm -f root/sbin/kdump
	rm -rf root/lib/kexec-tools  # kexec_test
	rm -rf root/usr/share  # man pages
	touch $@


# ----- Build kbd -------------------------------------------------------------


$(KBD_DIR)/.kboot-extracted: \
	  $(DL)/$(KBD_PACKAGE).ok
	rm -f $@ $(KBD_DIR)/.kboot-configured $(KBD_DIR)/.kboot-built
	tar xfz $(DL)/$(KBD_PACKAGE)
	patch -d $(KBD_DIR) -p1 -s \
	  <patches/kbd-bkeymap.patch
	touch $@

$(KBD_DIR)/.kboot-configured: \
	  $(KBD_DIR)/.kboot-extracted
	rm -f $@ $(KBD_DIR)/.kboot-built
	cd $(KBD_DIR) && ./configure
	touch $@

$(KBD_DIR)/.kboot-built: \
	  $(KBD_DIR)/.kboot-configured
	make -C $(KBD_DIR)
	touch $@

# ----- Build LILO ------------------------------------------------------------


# ----- kboot's utilities -----------------------------------------------------


utils/uclibc-readline: \
	  utils/readline.c build/installed/gcc-uclibc
	$(using_uclibc_cross) make -C utils CROSS=uclibc- uclibc-readline

utils/uclibc-getctty: \
	  utils/getctty.c build/installed/gcc-uclibc
	$(using_uclibc_cross) make -C utils CROSS=uclibc- uclibc-getctty

utils/uclibc-fsbyname: \
	  utils/fsbyname.c build/installed/gcc-uclibc
	$(using_uclibc_cross) make -C utils CROSS=uclibc- uclibc-fsbyname


# ----- keymaps ---------------------------------------------------------------


keymaps: \
	keymaps/.built

keymaps/.built: \
	  $(KBD_DIR)/.kboot-built
	mkdir -p keymaps
	find $(KBD_DIR)/data/keymaps -name '*.map' \
	  -exec sh -c '$(KBD_DIR)/src/loadkeys -b {} \
	  >keymaps/`basename {} .map`.bkeymap' ';'


# ----- Test-run the kboot shell ----------------------------------------------


try:
	-umount root/proc root/sys root/mnt/root root/mnt/root/boot \
	  root/mnt/tmp/*
	-umount root/dev/pts
	-rmdir root/mnt/tmp/*
	-stty_saved=`stty -g`; \
	  chroot root /init --dry-run; \
	  stty $$stty_saved
	-umount root/proc root/sys root/mnt/root root/mnt/root/boot \
	  root/mnt/tmp/*
	-umount root/dev/pts
	-rmdir root/mnt/tmp/*
	-pid=`cat root/var/run/dropbear.pid` && kill $$pid


# ---- Cleanup ----------------------------------------------------------------


reset:
	rm -f $(KERNEL_DIR)/.kboot-{extracted,configured,built}
	rm -f $(BINUTILS)/.kboot-{extracted,configured,built}
	rm -f $(GCC_DIR)/.kboot-extracted
	rm -f $(GCC_DIR)-host/.kboot-{configured,built}
	rm -f $(GCC_DIR)-uclibc/.kboot-{configured,built}
	rm -f $(UCLIBC_DIR)/.kboot-{extracted,configured,built}
	rm -f $(BUSYBOX_DIR)/.kboot-{extracted,configured,built}
	rm -f $(UDEV_DIR)/.kboot-{extracted,configured,built}
	rm -f $(KEXEC_TOOLS_DIR)/.kboot-{extracted,configured,built}
	rm -f $(DROPBEAR_DIR)-host/.kboot-{extracted,configured,built}
	rm -f $(DROPBEAR_DIR)-uclibc/.kboot-{extracted,configured,built}
#	rm -f $(LILO_DIR)/.kboot-{extracted,configured,built}
	rm -rf {root-meta,build}/installed root-meta/cache
	$(MAKE) -C utils clean

clean:
	rm -rf $(KERNEL_DIR)
	rm -rf $(BINUTILS_DIR)
	rm -rf $(GCC_DIR) $(GCC_DIR)-host $(GCC_DIR)-uclibc
	rm -rf $(UCLIBC_DIR)
	rm -rf $(BUSYBOX_DIR)
	rm -rf $(UDEV_DIR)
	rm -rf $(KEXEC_TOOLS_DIR)
	rm -rf $(DROPBEAR_DIR) $(DROPBEAR_DIR)-host $(DROPBEAR_DIR)-uclibc
#	rm -rf $(LILO_DIR)
	rm -rf build root root-meta keymaps
	$(MAKE) -C utils clean

spotless: \
	clean
	rm -f config/[abcdefghijklmnopqrstuvwxyz]*
	$(MAKE) -C utils spotless


# ----- Distribution ----------------------------------------------------------


SF_ACCOUNT=almesber@kboot.sourceforge.net
SF_DIR=/home/groups/k/kb/kboot/htdocs
SF_UPLOAD=$(SF_ACCOUNT):$(SF_DIR)/


dist:	kboot-$(KBOOT_VERSION).tar.gz

kboot-$(KBOOT_VERSION).tar.gz: \
	  $(FILES)
	rm -f kboot-$(KBOOT_VERSION)
	ln -sf . kboot-$(KBOOT_VERSION)
	tar cf - `for n in $(FILES); do \
	  echo kboot-$(KBOOT_VERSION)/$$n; done` | \
	  gzip -9 >kboot-$(KBOOT_VERSION).tar.gz || \
	  { rm -f kboot-$(KBOOT_VERSION).tar.gz; exit 1; }
	rm -f kboot-$(KBOOT_VERSION)

upload:	dist
	@echo -n "md5sum " && \
	  md5sum kboot-$(KBOOT_VERSION).tar.gz | sed 's/ .*//'
	@echo -n "sha1sum " && \
	  sha1sum kboot-$(KBOOT_VERSION).tar.gz | sed 's/ .*//'
	scp kboot-$(KBOOT_VERSION).tar.gz CHANGES $(SF_UPLOAD)
	ssh $(SF_ACCOUNT) $(SF_DIR)/release.sh $(SF_DIR) $(KBOOT_VERSION)
