#!/bin/busybox sh

set -o pipefail

mount -n -t proc proc /proc || fatal "Failure mount /proc"
echo 0 > /proc/sys/kernel/printk

mount -n -t devtmpfs devtmpfs /dev || fatal "Failure mount /dev"
mkdir -m 0755 /dev/pts || fatal "Failure create directory /dev/pts with perms 755"
mount -n -t devpts -o gid=5,mode=0620 devpts /dev/pts || fatal "Failure mount /dev/pts"
mount -n -t sysfs sysfs /sys || fatal "Failure mount /dev/pts"
mount -n -t tmpfs -o rw,nodev,mode=755 none /run || fatal "Failure mount /run"

cat <<EOF

        _____ __  __  ___   _   _   ___   _____ 
       |__  / \ \/ / |_ _| | \ | | |_ _| |_   _|
         / /   \  /   | |  |  \| |  | |    | |  
        / /_   /  \   | |  | |\  |  | |    | |  
       /____| /_/\_\ |___| |_| \_| |___|   |_| 

EOF


info() {
	if [ -z "$QUIET" ]; then
		echo " [I] $1"
	fi
}
warn() {
	echo " [W] $1"
}
fatal() {
	echo " [!] FATAL ERROR: $1"
	echo 1 > /proc/sys/kernel/printk
	echo ".Entering rescue shell."
	exec /bin/busybox sh
}

z_dhcp() {
	[ -n "$1" ] || fatal "z_dhcp(): Wrong argument error. Example: z_dhcp=\"eth0;eth1\""

	local FRIENDLY_ARGS=

	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')

	for DEV in ${FRIENDLY_ARGS}; do
		/sbin/ip link set up "${DEV}" || fatal "z_dhcp(): Failure set UP state for device ${DEV}."
		/sbin/udhcpc -i "${DEV}" -s /usr/share/udhcpc/default.script || fatal "z_dhcp(): Failure obtain lease for device ${DEV}." 
		echo "pkill -f /sbin/udhcpc" >> /tmp/cleanup.sh
	done
}

z_fsck() {
	[ -n "$1" ] || fatal "z_fsck(): Wrong argument error. Example: z_fsck=\"vg0/system,ext4;vg0/data,ext4\" (no /dev prefix)"

	local FRIENDLY_ARGS=
	local DEV=
	local FS=

	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')

	for CHECK in ${FRIENDLY_ARGS}; do
		DEV=$(echo "${CHECK}" | cut -d, -f1)
		FS=$(echo "${CHECK}" | cut -d, -f2)
		info "Force check file system ${FS} on /dev/${DEV}"
		/sbin/fsck -f -p -t "${FS}" -f "/dev/${DEV}" || warn "z_fsck(): Failure check filesystem on /dev/${DEV} (${FS})."
	done
}

z_ip() {
	[ -n "$1" ] || fatal "z_ip(): Wrong argument error. Example: z_ip=\"eth0,192.168.0.100/24[,192.168.0.1][;eth1,10.0.0.42/8[,10.0.0.254]]\")"
	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')
	for NETCFG in ${FRIENDLY_ARGS}; do
		local DEV=
		local IP_WITH_MASK=
		local GW=

		DEV=$(echo "${NETCFG}" | cut -d, -f1)
		IP_WITH_MASK=$(echo "${NETCFG}" | cut -d, -f2)
		GW=$(echo "${NETCFG}" | cut -d, -f3)

		local IP=
		local PREFIX=
		local MASK=

		IP=$(echo "${IP_WITH_MASK}" | cut -d/ -f1)
		PREFIX=$(echo "${IP_WITH_MASK}" | cut -d/ -f2)
		case "$PREFIX" in
			8)
				MASK=255.0.0.0
				;;
			16)
				MASK=255.255.0.0
				;;
			17)
				MASK=255.255.128.0
				;;
			18)
				MASK=255.255.192.0
				;;
			19)
				MASK=255.255.224.0
				;;
			20)
				MASK=255.255.240.0
				;;
			21)
				MASK=255.255.248.0
				;;
			22)
				MASK=255.255.252.0
				;;
			23)
				MASK=255.255.254.0
				;;
			24)
				MASK=255.255.255.0
				;;
			*)
				fatal "z_ip(): Unsupported IP prefix '$PREFIX'"
				;;
		esac

		info "Set up IP address: $IP $MASK for dev $DEV"
		ifconfig "$DEV" "$IP" netmask "$MASK" || fatal "Failure set IP address ${IP_WITH_MASK}."
		echo "ifconfig $DEV 0.0.0.0" >> /tmp/cleanup.sh
		echo "ifconfig $DEV down" >> /tmp/cleanup.sh

		if [ -z "$GW" ]; then
			info "Gateway is not defined"
		else
			info "Set up defult route: $GW"
			route add default gw "$GW" "$DEV" || fatal "Failure set default route to $GW from device $DEV."
		fi
	done
}

z_md() {
	[ -n "$1" ] || fatal "z_md():  Wrong argument error. Example: z_md=\"md0,sda1,[sdb1,...][;md1,sda5,[sdb5,...]]\""
	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')
	for MDTARGET in ${FRIENDLY_ARGS}; do
		local MD_DEV=
		local MEMBER_DEVS=

		MD_DEV=/dev/$(echo "${MDTARGET}" | cut -d, -f1)
		MEMBER_DEVS=$(echo "${MDTARGET}" | cut -d, -f2- | cut -d: -f2- | sed -r 's/,/ /g' | sed 's/[^ ]* */\/dev\/&/g')

		info " Assembling software RAID ${MD_DEV} on devices ${MEMBER_DEVS}..."
		/sbin/mdadm --assemble --run ${MD_DEV} ${MEMBER_DEVS} || fatal "z_md(): Failure MD assemble software RAID ${MD_DEV} on devices ${MEMBER_DEVS}"
		#/sbin/mdadm --assemble --update=name --run ${MD_DEV} ${MEMBER_DEVS} || fatal "z_md(): Cannot MD assemble: ${MD_DEV} ${MEMBER_DEVS}"
	done
}

z_quiet() {
	QUIET="yes"
}

z_pwd() {
	[ -n "$1" ] || fatal "z_pwd(): Wrong argument error. Example: z_pwd=\"P@ssw0rd\""
	info "	Set RAMFS password for user 'root'"
	echo "root:$1" | /bin/busybox chpasswd
}

z_root() {
	[ -n "$1" ] || fatal "z_root(): Wrong argument error. Example: z_root=\"vg0/system,ext3[,ro][,discard]\" (no /dev prefix)"

	local DEV=
	local FS=
	local MOUNTPOINT=
	DEV=$(echo "$1" | cut -d, -f1)
	FS=$(echo "$1" | cut -d, -f2)
	OPTS=$(echo "$1" | cut -d, -f3-)

	[ -z "$DEV" ] && fatal "z_root(): Argument error. Bad device."
	[ -z "$FS" ] && fatal "z_root(): Argument error. Bad filesystem type."

	info "Mount filesystem /dev/$DEV ($FS) to /newroot"
	[ -b "/dev/$DEV" ] || fatal "z_root(): Device /dev/$DEV does not exist."
	if [ ! -d /newroot ]; then
		mkdir /newroot || fatal "z_root(): Cannot create mountpoint /newroot"
	fi

	mount -o "$OPTS" -n -t "$FS" "/dev/$DEV" /newroot || fatal "z_root(): Failure mount /dev/$DEV to /newroot"
}

z_shell() {
	local COUNTDOWN=
	COUNTDOWN=0
	if [ -n "$1" ]; then
		let "COUNTDOWN=$1*1"
	fi

	if [ $COUNTDOWN -eq 0 ]; then
		echo
		info " Shell was started by z_shell(). Exit from current shell to continue init script."
		/bin/busybox sh
	else
		echo -n " Press 'S' to enter interactive shell..."

		while [ $COUNTDOWN -gt 0 ]; do
			let "COUNTDOWN=$COUNTDOWN-1"
			KEY=""
			read -t 1 -s -n 1 KEY
			if [ "$KEY" == "S" -o "$KEY" == "s" ]; then
				echo
				info " Shell was started by z_shell(). Exit from current shell to continue init script."
				/bin/busybox sh
				break;
			elif [ -n "$KEY" ]; then
				let "COUNTDOWN=$COUNTDOWN+1"
			fi
			echo -n " $COUNTDOWN"
		done
	fi
	echo
}

z_snap() {
	[ -n "$1" ] || fatal "z_snap(): Wrong argument error. Example: z_snap=\"vg0/luks-root,10G[,force];vg0/luks-home,250M\""

 	local FRIENDLY_ARGS=

	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')

	for SNAP in ${FRIENDLY_ARGS}; do
		local LV_DEV=
		local LV_SIZE=
		local LV_SNAPNAME=
		local LV_SNAPDEV=
		local FORCE=

		LV_DEV=/dev/$(echo "${SNAP}" | cut -d, -f1)
		LV_SIZE=$(echo "${SNAP}" | cut -d, -f2)
		LV_SNAPNAME=$(basename "${LV_DEV}")-bootsnap
		LV_SNAPDEV=$(dirname "${LV_DEV}")/${LV_SNAPNAME}
		FORCE=$(echo "${SNAP}" | cut -d, -f3)

		if [ -b "${LV_SNAPDEV}" ]; then
			if [ "${FORCE}" == "force" ]; then
				info "z_snap(): Removing previous snapshot"
				local LV_ORIGIN=
				LV_ORIGIN=$(/sbin/lvs "${LV_SNAPDEV}" | tail -n 1 | awk '{print $5}')
				[ -z "${LV_ORIGIN}" ] && fatal "z_snap(): Looks like ${LV_SNAPDEV} is not a snapshot(has not Pool Origin)! Something wrong in ZXInit configuration! Please check!"
				/sbin/lvremove -f "${LV_SNAPDEV}" || fatal "z_snap(): Failure remove LV snapshot ${LV_SNAPDEV}"
			else
				warn "z_snap(): Skip creation of boot snaphot due it already exist." 
			fi
		else
			info "z_snap(): Create LVM snapshot ${LV_SNAPNAME} (size: ${LV_SIZE}) for volume ${LV_DEV}"
			/sbin/lvcreate --snapshot --permission r --size "${LV_SIZE}" --name "${LV_SNAPNAME}" "${LV_DEV}" || fatal "Failure create LV snapshot."
		fi
	done
}

z_ssh() {
	[ ! -f /root/dropbear.rsa ] && /usr/bin/dropbearkey -t rsa -f /root/dropbear.rsa
	[ ! -f /root/dropbear.dss ] && /usr/bin/dropbearkey -t dss -f /root/dropbear.dss
	# /usr/bin/dropbearkey -t rsa -f /root/dropbear.rsa; /usr/bin/dropbearkey -t dss -f /root/dropbear.dss; strace /usr/sbin/dropbear -p 10022 -r /root/dropbear.rsa -d /root/dropbear.dss -F

	/usr/sbin/dropbear -r /root/dropbear.rsa -d /root/dropbear.dss || fatal "Failure start Dropbear SSH Server"
	echo "pkill -f /usr/sbin/dropbear" >> /tmp/cleanup.sh
}

__stratum__resolve_image_hash() {
	local TARGET_IMAGE_ID="$1"

	if (echo $TARGET_IMAGE_ID | grep -Eq "^[0-9a-f]{64}$"); then
		echo "${TARGET_IMAGE_ID}"
		return 0
	fi

	local IMAGE_MANIFEST_FILE="/run/stratum/images/${TARGET_IMAGE_ID}/MANIFEST"
	if [ -f "${IMAGE_MANIFEST_FILE}" ]; then
		local TAGET_IMAGE_HASH=
		TAGET_IMAGE_HASH=$(cat "${IMAGE_MANIFEST_FILE}" | grep -e "^SHA256: " | head -n 1 | rev | cut -d' ' -f1 | rev)
		if [ $? -ne 0 ]; then
			return 1
		fi
		echo -n "${TAGET_IMAGE_HASH}"
		return 0
	fi

	local IMAGE_MANIFEST_URL="http://dl.zxteam.net/stratum/images/${TARGET_IMAGE_ID}/MANIFEST"
	local REMOTE_MANIFEST_DATA=
	REMOTE_MANIFEST_DATA=$(curl --fail --silent "${IMAGE_MANIFEST_URL}")
	if [ $? -ne 0 ]; then
		return 2
	fi

	local TAGET_IMAGE_HASH=
	TAGET_IMAGE_HASH=$(echo "${REMOTE_MANIFEST_DATA}" | grep -e "^SHA256: " | head -n 1 | rev | cut -d' ' -f1 | rev)
	if [ $? -ne 0 ]; then
		return 3
	fi
	echo -n "${TAGET_IMAGE_HASH}"
}

__stratum__download_image() {
	local IMAGE_TAG="$1"
	if [ -z "${IMAGE_TAG}" ]; then
		return 127
	fi

	if ! (echo $IMAGE_TAG | grep -Eq "^[0-9a-f]{64}$"); then
		return 126
	fi

	local LOCAL_IMAGE_DIR="/run/stratum/images/${IMAGE_TAG}"
	if [ ! -d "${LOCAL_IMAGE_DIR}" ]; then

		local LOCAL_IMAGE_DIR_TEMP="/run/stratum/images/${IMAGE_TAG}.tmp"
		if [ -d "${LOCAL_IMAGE_DIR_TEMP}" ]; then
			# fatal "Cannot download image due temporary '${LOCAL_IMAGE_DIR_TEMP}' directory already exist."
			rm -rf "${LOCAL_IMAGE_DIR_TEMP}"
		fi

		local IMAGE_MANIFEST_URL="http://dl.zxteam.net/stratum/images/${IMAGE_TAG}/MANIFEST"
		local IMAGE_DATA_URL="http://dl.zxteam.net/stratum/images/${IMAGE_TAG}/DATA"

		mkdir -p "${LOCAL_IMAGE_DIR_TEMP}"
		if [ $? -ne 0 ]; then
			# fatal "Failure to create directory ${LOCAL_IMAGE_DIR_TEMP}"
			return 2
		fi
		info "Downloading MANIFEST of ${IMAGE_TAG} ..."
		curl "${IMAGE_MANIFEST_URL}" --fail --output "${LOCAL_IMAGE_DIR_TEMP}/MANIFEST"
		if [ $? -ne 0 ]; then
			rm -rf "${LOCAL_IMAGE_DIR_TEMP}"
			# fatal "Failure download MANIFEST of image ${IMAGE_TAG}"
			return 3
		fi
		echo
		info "Downloading DATA of ${IMAGE_TAG} ..."
		curl "${IMAGE_DATA_URL}" --fail --output "${LOCAL_IMAGE_DIR_TEMP}/DATA"
		if [ $? -ne 0 ]; then
			rm -rf "${LOCAL_IMAGE_DIR_TEMP}"
			# fatal "Failure download DATA of image ${IMAGE_TAG}"
			return 4
		fi
		echo

		mv "${LOCAL_IMAGE_DIR_TEMP}" "${LOCAL_IMAGE_DIR}"
		if [ $? -ne 0 ]; then
			rm -rf "${LOCAL_IMAGE_DIR_TEMP}"
			# fatal "Failure to rename ${LOCAL_IMAGE_DIR_TEMP} to ${LOCAL_IMAGE_DIR}"
			return 5
		fi

		info "Image ${IMAGE_TAG} was downloaded successfully."
	else
		echo "Image ${IMAGE_TAG} already exist. Skip download."
	fi
}

z_stratum_wipe() {
	[ -n "$1" ] || fatal "z_stratum_wipe(): Wrong argument error. Example: z_stratum_wipe=\"vg0/stratum-images,ext4,vg0/stratum-state,ext4\""

	local STRATUM_IMAGES_DEV=
	local STRATUM_IMAGES_FS=
	local STRATUM_STATE_DEV=
	local STRATUM_STATE_FS=
	local STRATUM_ROOT_IMAGE=

	STRATUM_IMAGES_DEV=/dev/$(echo "$1" | cut -d, -f1)
	STRATUM_IMAGES_FS=$(echo "$1" | cut -d, -f2)
	STRATUM_STATE_DEV=/dev/$(echo "$1" | cut -d, -f3)
	STRATUM_STATE_FS=$(echo "$1" | cut -d, -f4)

	mkfs.${STRATUM_IMAGES_FS} -L stratum-images -F -N 256    "${STRATUM_IMAGES_DEV}" || fatal "z_stratum_wipe(): Failure mkfs on \"${STRATUM_IMAGES_DEV}\""
	mkfs.${STRATUM_STATE_FS}  -L stratum-state  -F -N 524288 "${STRATUM_STATE_DEV}"  || fatal "z_stratum_wipe(): Failure mkfs on \"${STRATUM_STATE_DEV}\""
}

z_stratum_root() {
	[ -n "$1" ] || fatal "z_stratum_root(): Wrong argument error. Example: z_stratum_root=\"vg0/stratum-images,ext4,vg0/stratum-state,ext4,d6779c7557a8f32fc5f4d636f74925241d9cc37a18d2f27683c3e87e983611bf\""

	local STRATUM_IMAGES_DEV=
	local STRATUM_IMAGES_FS=
	local STRATUM_STATE_DEV=
	local STRATUM_STATE_FS=
	local STRATUM_ROOT_IMAGE=

	STRATUM_IMAGES_DEV=/dev/$(echo "$1" | cut -d, -f1)
	STRATUM_IMAGES_FS=$(echo "$1" | cut -d, -f2)
	STRATUM_STATE_DEV=/dev/$(echo "$1" | cut -d, -f3)
	STRATUM_STATE_FS=$(echo "$1" | cut -d, -f4)
	STRATUM_ROOT_IMAGE=$(echo "$1" | cut -d, -f5)

	mkdir /run/stratum || fatal "z_stratum_root(): Failure create directory /run/stratum"
	mkdir /run/stratum/images || fatal "z_stratum_root(): Failure create directory /run/stratum/images"
	mkdir /run/stratum/state || fatal "z_stratum_root(): Failure create directory /run/stratum/state"

	mount -t "${STRATUM_IMAGES_FS}" -o rw "${STRATUM_IMAGES_DEV}" /run/stratum/images || fatal "z_stratum_root(): Failure mount \"${STRATUM_IMAGES_DEV}\" to /run/stratum/images"
	info "z_stratum_root(): /run/stratum/images mounted from ${STRATUM_IMAGES_DEV}"

	mount -t "${STRATUM_STATE_FS}" -o rw "${STRATUM_STATE_DEV}" /run/stratum/state || fatal "z_stratum_root(): Failure mount \"${STRATUM_STATE_DEV}\" to /run/stratum/state"
	info "z_stratum_root(): /run/stratum/state mounted from ${STRATUM_STATE_DEV}"

	local LAYER_NUMBER=0
	local IMAGE_HASH=
	IMAGE_HASH=$(__stratum__resolve_image_hash "${STRATUM_ROOT_IMAGE}")
	local ROOT_IMAGE_HASH_RESOLUTION_CODE=$?
	if [ ${ROOT_IMAGE_HASH_RESOLUTION_CODE} -ne 0 ]; then
		fatal "z_stratum_root(): Cannot read remote MANIFEST data. Exit with code: ${ROOT_IMAGE_HASH_RESOLUTION_CODE}."
	fi
	info "z_stratum_root(): Root image hash: ${IMAGE_HASH}"

	local LOWERDIRS=

	local STATE_DIR="/run/stratum/state/${IMAGE_HASH}"

	if [ ! -d "${STATE_DIR}" ]; then
		mkdir "${STATE_DIR}" || fatal "z_stratum_root(): Failure create state dir ${STATE_DIR}"
		info "z_stratum_root(): ${STATE_DIR} state directory was created"
	fi

	while [ -n "${IMAGE_HASH}" ]; do
		local IMAGE_DIR="/run/stratum/images/${IMAGE_HASH}"
		local IMAGE_MANIFEST_FILE="${IMAGE_DIR}/MANIFEST"
		local IMAGE_DATA_FILE="${IMAGE_DIR}/DATA"

		if [ -d "${IMAGE_DIR}" ]; then
			if [ ! -f "${IMAGE_MANIFEST_FILE}" -o ! -f "${IMAGE_DATA_FILE}" ]; then
				warn "z_stratum_root(): Removing broken image dir \"${IMAGE_DIR}\" ..."
				rm -rf "${IMAGE_DIR}" || fatal "z_stratum_root(): Failure remove broken image dir \"${IMAGE_DIR}\""
			fi
		fi

		if [ ! -d "${IMAGE_DIR}" ]; then
			info "z_stratum_root(): Downloading image ${IMAGE_HASH} ..."
			__stratum__download_image "${IMAGE_HASH}"
		else
			info "z_stratum_root(): ${IMAGE_HASH} already exist"
		fi

		local LAYER_NAME="layer${LAYER_NUMBER}"
		local LAYER_DIR="${STATE_DIR}/${LAYER_NAME}"

		if [ ! -d "${LAYER_DIR}" ]; then
			mkdir "${LAYER_DIR}" || fatal "z_stratum_root(): Failure create layer dir ${STATE_DIR}"
			info "z_stratum_root(): ${LAYER_DIR} layer directory was created"
		fi

		mount -t squashfs -o ro,loop "${IMAGE_DATA_FILE}" "${LAYER_DIR}" || fatal "z_stratum_root(): Failure mount layer \"${IMAGE_DATA_FILE}\" to \"${LAYER_DIR}\""
		info "z_stratum_root(): ${IMAGE_DATA_FILE} layer image was mounted to ${LAYER_DIR}"

		if [ -n "${LOWERDIRS}" ]; then
			LOWERDIRS="${LOWERDIRS}:${LAYER_DIR}"
		else
			LOWERDIRS="${LAYER_DIR}"
		fi

		IMAGE_HASH=$(cat "${IMAGE_MANIFEST_FILE}" | grep -e "^BASE: " | rev | cut -d' ' -f1 | rev)
		let "LAYER_NUMBER=$LAYER_NUMBER+1"
	done

	mount -o remount,ro "${STRATUM_IMAGES_DEV}" || fatal "z_stratum_root(): Failure re-mount \"${STRATUM_IMAGES_DEV}\" as Read-Only."

	local WORK_DIR="${STATE_DIR}/.work"

	if [ ! -d "${WORK_DIR}" ]; then
		mkdir "${WORK_DIR}" || fatal "z_stratum_root(): Failure create layer dir ${WORK_DIR}"
		info "z_stratum_root(): ${WORK_DIR} work directory was created"
	fi

	local TOP_DIR="${STATE_DIR}/top"

	if [ ! -d "${TOP_DIR}" ]; then
		mkdir "${TOP_DIR}" || fatal "z_stratum_root(): Failure create layer dir ${TOP_DIR}"
		info "z_stratum_root(): ${TOP_DIR} top directory was created"
	fi

	mount -t overlay -o "ro,lowerdir=${LOWERDIRS},workdir=${WORK_DIR},upperdir=${TOP_DIR}" stratum_root /newroot || fatal "z_stratum_root(): Failure mount overlay /newroot based on ${LOWERDIRS}"
}

z_uncrypt() {
	[ -n "$1" ] || fatal "z_uncrypt(): Wrong argument error. Example: z_uncrypt=\"sda2,uncrypted-sda2[,discard][;vg0/luks-root,uncrypted-root[,discard]]\" (no /dev prefix)"
	/uncrypt "$1" || fatal "z_uncrypt(): Script /uncrypt failed."
	return 0
}

z_verbose() {
	set -x
}

z_vg() {
	[ -n "$1" ] || fatal "z_vg(): Wrong argument error. Example: z_vgs=\"vg0;vg1;vg2;...\" (no /dev prefix)"

	info " Scanning for Volume Groups"
	/sbin/vgscan || fatal "z_vg(): Failure scan volume groups"

 	local FRIENDLY_ARGS=

	FRIENDLY_ARGS=$(echo "$1" | sed -r 's/;/ /g')

	for VG in ${FRIENDLY_ARGS}; do
 		info " Activating Volume Group: $VG"
		/sbin/vgchange --activate y "$VG" || fatal "z_vg(): Failure activate volume $VG"
	done
}


# Set up busybox'es symlinks
/bin/busybox --install -s || fatal "Failure install busybox symlinks"

touch /var/log/lastlog || fatal "Failure create /var/log/lastlog"

ln -s /proc/mounts /etc/mtab || fatal "Failure link /etc/mtab -> /proc/mounts"

echo "Starting udev daemon..."
/bin/udevd --daemon --resolve-names=never
UDEV_RC=$?
udevadm trigger || fatal "Failure to trigger udev daemon"
udevadm settle || fatal "Failure to settle udev daemon"
[ $UDEV_RC -eq 0 ] || fatal "Failed to start udev daemon. Exit code: $UDEV_RC"
unset UDEV_RC

# Prepare cleanup script
echo "#!/bin/busybox sh" > /tmp/cleanup.sh
echo >> /tmp/cleanup.sh
echo "set -e" >> /tmp/cleanup.sh
echo >> /tmp/cleanup.sh
chmod +x /tmp/cleanup.sh || fatal "Failure make executeble cleanup script tmp/cleanup.sh"


# Kernel command-line
KCMD=$(cat "/proc/cmdline")

echo "Executing commands..."
for PARAM in $KCMD; do
	NAME=$(echo "$PARAM" | awk -F= '{print $1}')
	VALUE=$(echo "$PARAM" | awk -F= '{print $2}' | sed -e 's/^"//' -e 's/"$//')
	case "$NAME" in
		z_*)
			$NAME "$VALUE" || fatal "Failure execute $NAME $VALUE"
			;;
	esac
	unset NAME
	unset VALUE
done

echo "Stopping udev daemon..."
killall udevd
sleep 1

if [ -x /tmp/cleanup.sh ]; then
	echo "Executing cleanup script..."
	/tmp/cleanup.sh || fatal "Cleanup failed."
fi

if [ -d /newroot/lib ]; then
	KERNEL_RELEASE=$(uname -r)
	if [ -d "/lib/modules/${KERNEL_RELEASE}" ]; then
			if [ ! -d "/newroot/lib/modules/${KERNEL_RELEASE}" ]; then
				NEWROOT_MOUNT_OPTS=$(grep /newroot /proc/mounts | cut -d' ' -f4)
				if [ $? -ne 0 ]; then
					fatal "Failure obtain mount options of /newroot"
				fi
				info "Re-mounting the /newroot filesystem as RW to copy modules..."
				mount -o remount,rw /newroot || fatal "Failure re-mount /newroot as RW"
				if [ ! -d /newroot/lib/modules ]; then
					mkdir /newroot/lib/modules || fatal "Failure create /newroot/lib/modules directory"
				fi
				cp -a "/lib/modules/${KERNEL_RELEASE}" /newroot/lib/modules/ || fatal "Failure copy modules"
				info "Modules ${KERNEL_RELEASE} were copied into /newroot/lib/modules"

				info "Re-mounting the /newroot filesystem with original options '${NEWROOT_MOUNT_OPTS}' ..."
				mount -o "remount,${NEWROOT_MOUNT_OPTS}" /newroot || fatal "Failure re-mount /newroot as ${NEWROOT_MOUNT_OPTS}"

				sleep 3
			else
				info "Skip modules syncing. Looks like modules are same in initramfs and rootfs"
			fi
	else
		info "Skip modules syncing due the initramfs has not embedded kernel modules."
	fi

else
	warn "Modules from /lib/modules/${KERNEL_RELEASE} were not synced due directory /newroot/lib is not exist."
fi

# Clean up.
umount -n /sys || fatal "Failure umount /sys"
umount -n /dev/pts || fatal "Failure umount /dev/pts"
umount -n /dev || fatal "Failure umount /dev"

echo 1 > /proc/sys/kernel/printk

umount -n /proc || fatal "Failure umount /proc"

mount -o move /run /newroot/run || fatal "Failure move mount /run to /newroot/run"

# Boot the real thing.
exec switch_root /newroot /sbin/init $@