#!/bin/sh

# Default PATH differs between shells, and is not automatically exported
# by klibc dash.  Make it consistent.
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proc

# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
	case $x in
	initramfs.clear)
		clear
		;;
	quiet)
		quiet=y
		;;
	esac
done

if [ "$quiet" != "y" ]; then
	quiet=n
	echo "Loading, please wait..."
fi
export quiet

# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
mount -t devtmpfs -o nosuid,mode=0755 udev /dev

mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true

# Export the dpkg architecture
export DPKG_ARCH=
. /conf/arch.conf

# Set modprobe env
export MODPROBE_OPTIONS="-qb"

# Export relevant variables
export ROOT=
export ROOTDELAY=
export ROOTFLAGS=
export ROOTFSTYPE=
export IP=
export DEVICE=
export BOOT=
export BOOTIF=
export UBIMTD=
export break=
export init=/sbin/init
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export btrfs_blacklist=
export resume=
export resume_offset=
export noresume=
export drop_caps=
export fastboot=n
export forcefsck=n
export fsckfix=
export IP6=
export VLAN=
export NETWORK_SKIP_ENSLAVED=
export LIVE_BOOT_CMDLINE=
export origin_root=
export origin_rootmnt=

# mdadm needs hostname to be set. This has to be done before the udev rules are called!
if [ -f "/etc/hostname" ]; then
        /bin/hostname -F /etc/hostname >/dev/null 2>&1
fi


# Bring in the main config
. /conf/initramfs.conf
for conf in conf/conf.d/*; do
	[ -f "${conf}" ] && . "${conf}"
done
. /scripts/functions

# Parse command line options
# shellcheck disable=SC2013
for x in $(cat /proc/cmdline); do
	case $x in
	# The following lines blocked for security reason
	init=*)
		init=${x#init=}
		;;
	root=*)
		ROOT=${x#root=}
		if [ -z "${BOOT}" ] && [ "$ROOT" = "/dev/nfs" ]; then
			BOOT=nfs
		fi
		;;
	rootflags=*)
		ROOTFLAGS="-o ${x#rootflags=}"
		;;
	rootfstype=*)
		ROOTFSTYPE="${x#rootfstype=}"
		;;
	rootdelay=*)
		ROOTDELAY="${x#rootdelay=}"
		case ${ROOTDELAY} in
		*[![:digit:].]*)
			ROOTDELAY=
			;;
		esac
		;;
	roottimeout=*)
		ROOTDELAY="${x#roottimeout=}"
		case ${ROOTDELAY} in
		*[![:digit:].]*)
			ROOTDELAY=
			;;
		esac
		;;
	loop=*)
		# shellcheck disable=SC2034
		LOOP="${x#loop=}"
		;;
	loopflags=*)
		# shellcheck disable=SC2034
		LOOPFLAGS="-o ${x#loopflags=}"
		;;
	loopfstype=*)
		# shellcheck disable=SC2034
		LOOPFSTYPE="${x#loopfstype=}"
		;;
	ip6=*)
		IP6="${x#ip6=}"
		;;
	vlan=*)
		VLAN="${x#vlan=}"
		;;
	nfsroot=*)
		# shellcheck disable=SC2034
		NFSROOT="${x#nfsroot=}"
		;;
	initramfs.runsize=*)
		RUNSIZE="${x#initramfs.runsize=}"
		;;
	ip=*)
		IP="${x#ip=}"
		;;
	boot=*)
		BOOT=${x#boot=}
		;;
	ubi.mtd=*)
		UBIMTD=${x#ubi.mtd=}
		;;
	resume=*)
		RESUME="${x#resume=}"
		case $RESUME in
		UUID=*)
			RESUME="/dev/disk/by-uuid/${RESUME#UUID=}"
		esac
		;;
	resume_offset=*)
		resume_offset="${x#resume_offset=}"
		;;
	noresume)
		noresume=y
		;;
	drop_capabilities=*)
		drop_caps="-d ${x#drop_capabilities=}"
		;;
	panic=*)
		panic="${x#panic=}"
		case ${panic} in
        -1) ;;
		*[![:digit:].]*)
			panic=
			;;
		esac
		;;
	ro)
		readonly=y
		;;
	rw)
		readonly=n
		;;
	debug)
		debug=y
		quiet=n
		if [ -n "${netconsole}" ]; then
			log_output=/dev/kmsg
		else
			log_output=/run/initramfs/initramfs.debug
		fi
		set -x
		;;
	debug=*)
		debug=y
		quiet=n
		set -x
		;;
	break=*)
		break=${x#break=}
		;;
	break)
		break=premount
		;;
	blacklist=*)
		blacklist=${x#blacklist=}
		;;
	netconsole=*)
		netconsole=${x#netconsole=}
		[ "x$debug" = "xy" ] && log_output=/dev/kmsg
		;;
	BOOTIF=*)
		BOOTIF=${x#BOOTIF=}
		;;
	hwaddr=*)
		BOOTIF=${x#hwaddr=}
		;;
	fastboot|fsck.mode=skip)
		fastboot=y
		;;
	forcefsck|fsck.mode=force)
		forcefsck=y
		;;
	fsckfix|fsck.repair=yes)
		fsckfix=y
		;;
	fsck.repair=no)
		fsckfix=n
		;;
	esac
done

# Default to BOOT=local if no boot script defined.
if [ -z "${BOOT}" ]; then
	BOOT=local
fi

if [ -n "${noresume}" ] || [ "$RESUME" = none ]; then
	noresume=y
else
	resume=${RESUME:-}
fi

mount -t tmpfs -o "nodev,noexec,nosuid,size=${RUNSIZE:-10%},mode=0755" tmpfs /run
mkdir -m 0700 /run/initramfs


if [ -n "$log_output" ]; then
	exec >$log_output 2>&1
	unset log_output
fi

maybe_break top

# For hisi sas dirver take 3 to 4 seconds to init, so dont init hisi sas driver here when root disk dont use sas controller.
# And at initrd phase,dont init btrfs.
root_uuid=${ROOT#UUID=}
#echo "root_uuid:${root_uuid}"
kernel_type="$(uname -r | grep desktop)"
#echo "kernel_type:${kernel_type}"
if [ -n "${root_uuid}" ];then


	btrfs_blacklist="raid6_pq"

	if [ -f "/dev/disk/by-uuid/${root_uuid}" ]; then

		if [ -n "${kernel_type}" ];then
#			echo "-->desktop"
			if [ -z "${blacklist}" ];then
				blacklist="scsi_transport_sas,libsas,hisi_sas_main,hisi_sas_v3_hw,${btrfs_blacklist}"
			else
				blacklist=${blacklist}",scsi_transport_sas,libsas,hisi_sas_main,hisi_sas_v3_hw,${btrfs_blacklist}"
			fi
		fi
	else
		if [ -n "${kernel_type}" ];then
#			echo "-->desktop sas"
			if [ -z "${blacklist}" ];then
				blacklist="${btrfs_blacklist}"
			else
				blacklist=${blacklist}",${btrfs_blacklist}"
			fi
		fi
	fi
fi

# export BOOT variable value for compcache,
# so we know if we run from casper
export BOOT

# Don't do log messages here to avoid confusing graphical boots
run_scripts /scripts/init-top

maybe_break modules
[ "$quiet" != "y" ] && log_begin_msg "Loading essential drivers"
[ -n "${netconsole}" ] && modprobe netconsole netconsole="${netconsole}"
load_modules
[ "$quiet" != "y" ] && log_end_msg

if [ "$ROOTDELAY" ]; then
	sleep $ROOTDELAY
fi

maybe_break premount
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount"
run_scripts /scripts/init-premount
[ "$quiet" != "y" ] && log_end_msg

maybe_break mount
log_begin_msg "Mounting root file system"
# Always load local and nfs (since these might be needed for /etc or
# /usr, irrespective of the boot script used to mount the rootfs).
LIVE_BOOT_CMDLINE="${LIVE_BOOT_CMDLINE:-$(cat /proc/cmdline)}"
real_boot=${BOOT}
result=$(echo "${ROOT}" | grep "UUID")
[ "${result}" != "" ] && [ "${BOOT}" = "live" ] && BOOT=local
. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric "${ROOT}"
maybe_break mountroot
mount_top
mount_premount
mountroot

if [ -e "${rootmnt}/live.flag" ]; then
        mount -o rw,remount ${rootmnt}
        rm -f ${rootmnt}/live.flag
        real_boot=live
        LIVE_BOOT_CMDLINE="$LIVE_BOOT_CMDLINE  boot=live  toram=filesystem.squashfs locales=zh_CN.UTF-8 live-media-path=usr/doppel"
fi

if [ -e "${rootmnt}/SystemdLocalfsDependencyFailed.flag" ]; then
        if echo "${LIVE_BOOT_CMDLINE}" | grep -q "boot=live"; then
                mount -o rw,remount ${rootmnt}
                rm ${rootmnt}/SystemdLocalfsDependencyFailed.flag
        else
                mount -o rw,remount ${rootmnt}
                echo "Loading file repair system..."
                rm ${rootmnt}/SystemdLocalfsDependencyFailed.flag
                panic
        fi
fi

# Clean up the "/tmp/*" directory in the system disk to ensure that the available space of the
# "/" directory is > 500K
clean_system_disk() {
    # Define local variables
    local rootDiskStandard=500           # Required free space: > 500KB
    local RootIsFullFile="RootIsFull.flag"
    local RootIsFullFilePath="${rootmnt}/${RootIsFullFile}"
    local root_disk_cleaned_space=""

    # 1. Check if RootIsFull.flag exists
    if [ ! -e "${RootIsFullFilePath}" ]; then
        log_success_msg "${RootIsFullFilePath} not found. Skipping system disk cleanup."
        return 0
    fi

    # 2. Try to remount root as read-write (best effort)
    if ! mount -o rw,remount "${rootmnt}" 2>/dev/null; then
        log_warning_msg "Failed to remount ${rootmnt} as rw. Proceeding anyway."
        # Do not panic on remount failure and need to check free space
    fi

    # 3. Clean up /tmp directory
    rm -rf "${rootmnt}/tmp/"* 2>/dev/null || true

    # 4. Get available space on root filesystem (in KB)
    root_disk_cleaned_space=$(df -Bk "${rootmnt}" | awk 'END { print $(NF-2) }')

    # 5. Only panic if we successfully got a valid number AND it's <= threshold
    if [ -n "${root_disk_cleaned_space}" ] && echo "${root_disk_cleaned_space}" | grep -qE '^[0-9]+$'; then
        if [ "${root_disk_cleaned_space}" -gt "${rootDiskStandard}" ]; then
            # Sufficient space
            rm -f "${RootIsFullFilePath}" || true
            log_success_msg "System disk cleanup successful. Sufficient space: ${root_disk_cleaned_space} KB. Flag removed."
        else
            # Space is insufficient (valid measurement, but too small)
            echo "CRITICAL: Root disk space insufficient after cleanup: ${root_disk_cleaned_space} KB <= ${rootDiskStandard} KB"
            echo "We must ensure / available size > ${rootDiskStandard} KB"
            panic
        fi
    else
        # Failed to get valid space value (e.g., df failed, awk no match, etc.)
        log_warning_msg "Could not get valid available space for ${rootmnt}. Assuming sufficient space."
    fi
}



# Clean up "/data/var/cache/apt/archives" and "/data/var/log" in the data disk to ensure that
# the available space of the "/data" directory is > 100M
clean_data_disk() {
    # Define local variables
    local log_disk_threshold=20        # Clean /var/log if size > 20MB
    local data_disk_threshold=100      # Required available space: 100MB
    local DataIsFullFile="DataIsFull.flag"
    local DataIsFullFilePath="${rootmnt}/${DataIsFullFile}"
    local get_data_disk_uuid=""
    local tmpdata="tmpdata"
    local data_mount="/tmp/${tmpdata}"
    local data_disk_name=""
    local log_used_dir_space=0
    local data_disk_cleaned_space=""

    # 1. Check if flag file exists
    if [ ! -e "${DataIsFullFilePath}" ]; then
        log_success_msg "${DataIsFullFilePath} not found. Skipping data disk cleanup."
        return 0
    fi

    # 2. Read UUID from the last line of flag file
    get_data_disk_uuid=$(tail -n 1 "${DataIsFullFilePath}" | tr -d ' \t\n\r')
    if [ -z "${get_data_disk_uuid}" ]; then
        log_warning_msg "UUID is empty in ${DataIsFullFilePath}. Treating as normal boot."
        return 0
    fi

    # 3. Remount root as read-write (best effort)
    if ! mount -o rw,remount "${rootmnt}" 2>/dev/null; then
        log_warning_msg "Failed to remount ${rootmnt} as rw. Proceeding anyway."
    fi

    # 4. Find device by UUID
    data_disk_name=$(blkid -t UUID="${get_data_disk_uuid}" | awk -F: '{print $1}' | head -n1)
    if [ -z "${data_disk_name}" ]; then
        log_warning_msg "No device found for UUID=${get_data_disk_uuid}. Assuming sufficient space."
        return 0
    fi

    # 5. Create mount point
    mkdir -p "${data_mount}"

    # 6. Mount data partition
    if ! mount -o rw "${data_disk_name}" "${data_mount}"; then
        log_warning_msg "Failed to mount ${data_disk_name}. Assuming cleanup not needed."
        return 0
    fi

    # 7. Clean APT cache
    rm -rf "${data_mount}/var/cache/apt/archives" 2>/dev/null || true

    # 8. Clean /var/log if it exceeds threshold
    if [ -d "${data_mount}/var/log" ]; then
        log_used_dir_space=$(du -sm "${data_mount}/var/log" 2>/dev/null | awk '{print $1}' || echo "")
        # If du fails or output is not a number, skip log cleaning but don't panic
        if [ -n "${log_used_dir_space}" ] && echo "${log_used_dir_space}" | grep -qE '^[0-9]+$'; then
            if [ "${log_used_dir_space}" -gt "${log_disk_threshold}" ]; then
                rm -rf "${data_mount}/var/log" 2>/dev/null || true
            fi
        else
            log_warning_msg "Could not determine /var/log size, skipping cleanup."
        fi
    fi

    # 9. Get available space after cleanup (in MB)
    data_disk_cleaned_space=$(df -Bm "${data_mount}" | awk 'END { print $(NF-2) }')

    # 10. Only panic if we successfully got a number AND it's below threshold
    if [ -n "${data_disk_cleaned_space}" ] && echo "${data_disk_cleaned_space}" | grep -qE '^[0-9]+$'; then
        if [ "${data_disk_cleaned_space}" -lt "${data_disk_threshold}" ]; then
            echo "CRITICAL: Data disk space insufficient after cleanup: ${data_disk_cleaned_space} KB < ${data_disk_threshold} MB"
            echo "We must ensure /data available size > ${data_disk_threshold} MB"
            panic
        else
            rm -f "${DataIsFullFilePath}" || true
            log_success_msg "Data disk check passed. Flag removed. Continuing boot."
        fi
    else
        log_warning_msg "Could not get valid available space value. Assuming sufficient space."
    fi

	umount "${data_mount}" 2>/dev/null || true
}

if ! echo "${LIVE_BOOT_CMDLINE}" | grep -q "boot=live"; then
	clean_system_disk
	clean_data_disk
fi

uos_check_init() {
	local allowed_script="/usr/bin/deepinisocheck.sh"
	local default_init="/sbin/init"

	# Allow specific script directly without further checks
	if [ "$init" = "$allowed_script" ] || [ "$init" = "$default_init" ]; then
		return 0
	fi

	# Mount /boot only if it's defined in fstab
	if read_fstab_entry /boot; then
		log_begin_msg "Mounting /boot file system"
		if ! mountfs /boot; then
			log_warn_msg "Failed to mount /boot"
			return 1
		fi
		log_end_msg

		# Check GRUB config for password_pbkdf2 (menu encryption)
		local grub_cfg="${rootmnt}/boot/grub/grub.cfg"
		if [ ! -f "$grub_cfg" ] || ! grep -q '^password_pbkdf2' "$grub_cfg"; then
			log_warn_msg "GRUB encryption not detected, resetting init to default: $default_init"
			init=$default_init
		fi

		# Unmount /boot after use
		umount "${rootmnt}/boot"
	else
		log_warn_msg "/boot not found in fstab, resetting init to default: $default_init"
		init=$default_init
	fi
}
uos_check_init

if [ "${real_boot}" = "live" ] && [ "${BOOT}" = "local" ]; then
        origin_root=${ROOT}
        umount ${rootmnt}
        LIVE_BOOT_CMDLINE="$LIVE_BOOT_CMDLINE bootfrom=${ROOT}"
        BOOT=live
        . /scripts/local
        . /scripts/nfs
        . /scripts/${BOOT}
        parse_numeric "${ROOT}"
        maybe_break mountroot
        mount_top
        mount_premount
        mountroot

        origin_rootmnt="/tmp"
        mount -r "${origin_root}" "${origin_rootmnt}"
        kernel_version="$(uname -r)"
        src_dir="${origin_rootmnt}/lib/modules/${kernel_version}/"
        dst_dir="${rootmnt}/lib/modules/"
        rm -rf ${dst_dir}*
        mkdir -p "${dst_dir}${kernel_version}"
        substance_list=$(ls "${src_dir}")
        for substance in ${substance_list}; do
            cp -rf "${src_dir}${substance}" "${dst_dir}${kernel_version}"
        done
        cp -rf "${origin_rootmnt}/etc/modules-load.d"     "${rootmnt}/etc/"
        cp -rf "${origin_rootmnt}/usr/lib/modules-load.d"  "${rootmnt}/usr/lib/"
        cp -a "${origin_rootmnt}/usr/share/fonts" "${rootmnt}/usr/share/"
        cp -a "${origin_rootmnt}/etc/crypttab" "${rootmnt}/etc/crypttab"
        cp -rf "${origin_rootmnt}/usr/share/X11/xorg.conf.d" "${rootmnt}/usr/share/X11/"
        if [ "$(grep -w LOCAL ${origin_rootmnt}/etc/adjtime)" = "LOCAL" ]; then
            cp -a "${origin_rootmnt}/etc/adjtime" "${rootmnt}/etc/adjtime"
            rm -rf "${rootmnt}/etc/localtime"
            cp -a "${origin_rootmnt}/etc/localtime" "${rootmnt}/etc/localtime"
        fi
        if [ -e ${origin_rootmnt}/etc/nvidia/current/nvidia-blacklists-nouveau.conf ]; then
            rm -rf "${dst_dir}${kernel_version}"/updates/dkms/nvidia*.ko
            echo "blacklist nvidiafb" > ${rootmnt}/etc/modprobe.d/nvidia-blacklists-nouveau.conf
        fi

        arch_type="$(uname -m)"
        if [ -e ${origin_rootmnt}/usr/lib/xorg/modules/drivers/cx4_drv.so ]; then
            cp -rf "${origin_rootmnt}/usr/lib/xorg/modules/drivers/cx4_drv.so" "${rootmnt}/usr/lib/xorg/modules/drivers/"
            cp -rf "${origin_rootmnt}/usr/lib/${arch_type}-linux-gnu"/libcx4* "${rootmnt}/usr/lib/${arch_type}-linux-gnu/"
        fi


        if [ -e ${origin_rootmnt}/usr/share/X11/xorg.conf.d/10-innogpu.conf ]; then
            cp -rf "${origin_rootmnt}/usr/share/X11/xorg.conf.d/10-innogpu.conf"  "${rootmnt}/usr/share/X11/xorg.conf.d/"
        fi

        if [ -e ${origin_rootmnt}/etc/X11/xorg.conf.d/100-huawei.conf ]; then
            cp -rf "${origin_rootmnt}/etc/X11/xorg.conf.d/100-huawei.conf"  "${rootmnt}/etc/X11/xorg.conf.d/"
        fi
        umount ${origin_rootmnt}
fi
log_end_msg

if read_fstab_entry /usr; then
	log_begin_msg "Mounting /usr file system"
	mountfs /usr
	log_end_msg
fi


# Mount cleanup
mount_bottom
nfs_bottom
local_bottom

maybe_break bottom
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom"
# We expect udev's init-bottom script to move /dev to ${rootmnt}/dev
run_scripts /scripts/init-bottom
[ "$quiet" != "y" ] && log_end_msg

# Move /run to the root
mount -n -o move /run ${rootmnt}/run

validate_init() {
	run-init -n "${rootmnt}" "${1}"
}


# Check init is really there
if ! validate_init "$init"; then
	echo "Target filesystem doesn't have requested ${init}."
	init=
	for inittest in /sbin/init /etc/init /bin/init /bin/sh; do
		if validate_init "${inittest}"; then
			init="$inittest"
			break
		fi
	done
fi

# No init on rootmount
if ! validate_init "${init}" ; then
	panic "No init found. Try passing init= bootarg."
fi

maybe_break init

# don't leak too much of env - some init(8) don't clear it
# (keep init, rootmnt, drop_caps)
unset debug
unset MODPROBE_OPTIONS
unset DPKG_ARCH
unset ROOTFLAGS
unset ROOTFSTYPE
unset ROOTDELAY
unset ROOT
unset IP
unset BOOT
unset BOOTIF
unset DEVICE
unset UBIMTD
unset blacklist
unset break
unset noresume
unset panic
unset quiet
unset readonly
unset resume
unset resume_offset
unset noresume
unset fastboot
unset forcefsck
unset fsckfix
unset IP6
unset VLAN

# Move virtual filesystems over to the real filesystem
mount -n -o move /sys ${rootmnt}/sys
mount -n -o move /proc ${rootmnt}/proc

# Chain to real filesystem
# shellcheck disable=SC2086,SC2094
exec run-init ${drop_caps} "${rootmnt}" "${init}" "$@" <"${rootmnt}/dev/console" >"${rootmnt}/dev/console" 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."
