diff --git a/SOURCES/60-kdump.install b/SOURCES/60-kdump.install
new file mode 100755
index 0000000..0a3b40e
--- /dev/null
+++ b/SOURCES/60-kdump.install
@@ -0,0 +1,30 @@
+#!/usr/bin/bash
+
+COMMAND="$1"
+KERNEL_VERSION="$2"
+BOOT_DIR_ABS="$3"
+KERNEL_IMAGE="$4"
+
+if ! [[ ${KERNEL_INSTALL_MACHINE_ID-x} ]]; then
+    exit 0
+fi
+
+if [[ -d "$BOOT_DIR_ABS" ]]; then
+    KDUMP_INITRD="initrdkdump"
+else
+    BOOT_DIR_ABS="/boot"
+    KDUMP_INITRD="initramfs-${KERNEL_VERSION}kdump.img"
+fi
+
+ret=0
+case "$COMMAND" in
+    add)
+        # Do nothing, kdump initramfs is strictly host only
+        # and managed by kdump service
+        ;;
+    remove)
+        rm -f -- "$BOOT_DIR_ABS/$KDUMP_INITRD"
+        ret=$?
+        ;;
+esac
+exit $ret
diff --git a/SOURCES/dracut-early-kdump-module-setup.sh b/SOURCES/dracut-early-kdump-module-setup.sh
index e069867..f30bd67 100755
--- a/SOURCES/dracut-early-kdump-module-setup.sh
+++ b/SOURCES/dracut-early-kdump-module-setup.sh
@@ -21,18 +21,13 @@ depends() {
 }
 
 prepare_kernel_initrd() {
-    KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}")
-    if [ -z "$KDUMP_KERNELVER" ]; then
-        kdump_kver=`uname -r`
-        if [ "$kernel" != "$kdump_kver" ]; then
-            dwarn "Using current kernel version '$kdump_kver' for early kdump," \
-                "but the initramfs is generated for kernel version '$kernel'"
-        fi
-    else
-        kdump_kver=$KDUMP_KERNELVER
+    prepare_kdump_bootinfo
+
+    # $kernel is a variable from dracut
+    if [ "$KDUMP_KERNELVER" != $kernel ]; then
+        dwarn "Using kernel version '$KDUMP_KERNELVER' for early kdump," \
+            "but the initramfs is generated for kernel version '$kernel'"
     fi
-    KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
-    KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img"
 }
 
 install() {
@@ -58,8 +53,8 @@ install() {
     inst_binary "$KDUMP_KERNEL"
     inst_binary "$KDUMP_INITRD"
 
-    ln_r "$KDUMP_KERNEL" "${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}"
-    ln_r "$KDUMP_INITRD" "${KDUMP_BOOTDIR}/initramfs-earlykdump.img"
+    ln_r "$KDUMP_KERNEL" "/boot/kernel-earlykdump"
+    ln_r "$KDUMP_INITRD" "/boot/initramfs-earlykdump"
 
     chmod -x "${initdir}/$KDUMP_KERNEL"
 }
diff --git a/SOURCES/dracut-early-kdump.sh b/SOURCES/dracut-early-kdump.sh
index 69a34eb..92913fb 100755
--- a/SOURCES/dracut-early-kdump.sh
+++ b/SOURCES/dracut-early-kdump.sh
@@ -16,10 +16,8 @@ EARLY_KEXEC_ARGS=""
 prepare_parameters()
 {
     EARLY_KDUMP_CMDLINE=$(prepare_cmdline "${KDUMP_COMMANDLINE}" "${KDUMP_COMMANDLINE_REMOVE}" "${KDUMP_COMMANDLINE_APPEND}")
-    KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}")
-
-    EARLY_KDUMP_KERNEL="${KDUMP_BOOTDIR}/${KDUMP_IMG}-earlykdump${KDUMP_IMG_EXT}"
-    EARLY_KDUMP_INITRD="${KDUMP_BOOTDIR}/initramfs-earlykdump.img"
+    EARLY_KDUMP_KERNEL="/boot/kernel-earlykdump"
+    EARLY_KDUMP_INITRD="/boot/initramfs-earlykdump"
 }
 
 early_kdump_load()
diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh
index 32506ad..5b3f126 100755
--- a/SOURCES/dracut-module-setup.sh
+++ b/SOURCES/dracut-module-setup.sh
@@ -759,6 +759,30 @@ remove_cpu_online_rule() {
     sed -i '/SUBSYSTEM=="cpu"/d' $file
 }
 
+kdump_install_systemd_conf() {
+    local failure_action=$(get_option_value "failure_action")
+
+    # Kdump turns out to require longer default systemd mount timeout
+    # than 1st kernel(90s by default), we use default 300s for kdump.
+    grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null
+    if [ $? -ne 0 ]; then
+        mkdir -p ${initdir}/etc/systemd/system.conf.d
+        echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf
+        echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf
+    fi
+
+    # Forward logs to console directly, and don't read Kmsg, this avoids
+    # unneccessary memory consumption and make console output more useful.
+    # Only do so for non fadump image.
+    if ! is_fadump_capable; then
+        mkdir -p ${initdir}/etc/systemd/journald.conf.d
+        echo "[Journal]" > ${initdir}/etc/systemd/journald.conf.d/kdump.conf
+        echo "Storage=volatile" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf
+        echo "ReadKMsg=no" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf
+        echo "ForwardToConsole=yes" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf
+    fi
+}
+
 install() {
     local arch
 
@@ -807,6 +831,8 @@ install() {
     # at some point of time.
     kdump_check_iscsi_targets
 
+    kdump_install_systemd_conf
+
     # For the lvm type target under kdump, in /etc/lvm/lvm.conf we can
     # safely replace "reserved_memory=XXXX"(default value is 8192) with
     # "reserved_memory=1024" to lower memory pressure under kdump. We do
@@ -816,25 +842,8 @@ install() {
       's/\(^[[:space:]]*reserved_memory[[:space:]]*=\)[[:space:]]*[[:digit:]]*/\1 1024/' \
       ${initdir}/etc/lvm/lvm.conf &>/dev/null
 
-    # Kdump turns out to require longer default systemd mount timeout
-    # than 1st kernel(90s by default), we use default 300s for kdump.
-    grep -r "^[[:space:]]*DefaultTimeoutStartSec=" ${initdir}/etc/systemd/system.conf* &>/dev/null
-    if [ $? -ne 0 ]; then
-        mkdir -p ${initdir}/etc/systemd/system.conf.d
-        echo "[Manager]" > ${initdir}/etc/systemd/system.conf.d/kdump.conf
-        echo "DefaultTimeoutStartSec=300s" >> ${initdir}/etc/systemd/system.conf.d/kdump.conf
-    fi
-
+    # Save more memory by dropping switch root capability
     if ! is_fadump_capable; then
-        # Forward logs to console directly, this avoids unneccessary memory
-        # consumption and make console output more useful.
-        # Only do so for non fadump image.
-        mkdir -p ${initdir}/etc/systemd/journald.conf.d
-        echo "[Journal]" > ${initdir}/etc/systemd/journald.conf.d/kdump.conf
-        echo "Storage=none" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf
-        echo "ForwardToConsole=yes" >> ${initdir}/etc/systemd/journald.conf.d/kdump.conf
-
-        # Save more memory by dropping switch root capability
         dracut_no_switch_root
     fi
 }
diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh
index 2a7b613..3a80efb 100755
--- a/SOURCES/kdump-lib-initramfs.sh
+++ b/SOURCES/kdump-lib-initramfs.sh
@@ -4,7 +4,7 @@
 
 KDUMP_PATH="/var/crash"
 CORE_COLLECTOR=""
-DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 1 -d 31"
+DEFAULT_CORE_COLLECTOR="makedumpfile -l --message-level 7 -d 31"
 DMESG_COLLECTOR="/sbin/vmcore-dmesg"
 FAILURE_ACTION="systemctl reboot -f"
 DATEDIR=`date +%Y-%m-%d-%T`
diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh
index 3abd707..f5a7012 100755
--- a/SOURCES/kdump-lib.sh
+++ b/SOURCES/kdump-lib.sh
@@ -326,6 +326,11 @@ is_ipv6_auto()
     fi
 }
 
+is_atomic()
+{
+    grep -q "ostree" /proc/cmdline
+}
+
 is_ipv6_address()
 {
     echo $1 | grep -q ":"
@@ -617,6 +622,7 @@ is_secure_boot_enforced()
 		return 0
     fi
 
+    # Detect secure boot on x86 and arm64
     secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null)
     setup_mode_file=$(find /sys/firmware/efi/efivars -name SetupMode-* 2>/dev/null)
 
@@ -629,6 +635,11 @@ is_secure_boot_enforced()
         fi
     fi
 
+    # Detect secure boot on s390x
+    if [[ -e "/sys/firmware/ipl/secure" && "$(cat /sys/firmware/ipl/secure)" == "1" ]]; then
+        return 0
+    fi
+
     return 1
 }
 
@@ -666,24 +677,68 @@ prepare_kexec_args()
     echo $kexec_args
 }
 
-check_boot_dir()
+#
+# Detect initrd and kernel location, results are stored in global enviromental variables:
+# KDUMP_BOOTDIR, KDUMP_KERNELVER, KDUMP_KERNEL, DEFAULT_INITRD, and KDUMP_INITRD
+#
+# Expectes KDUMP_BOOTDIR, KDUMP_IMG, KDUMP_IMG_EXT, KDUMP_KERNELVER to be loaded from config already
+# and will prefer already set values so user can specify custom kernel/initramfs location
+#
+prepare_kdump_bootinfo()
 {
-    local kdump_bootdir=$1
-    #If user specify a boot dir for kdump kernel, let's use it. Otherwise
-    #check whether it's a atomic host. If yes parse the subdirectory under
-    #/boot; If not just find it under /boot.
-    if [ -n "$kdump_bootdir" ]; then
-        echo "$kdump_bootdir"
-        return
+    local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)"
+    local machine_id
+
+    if [ -z "$KDUMP_KERNELVER"]; then
+        KDUMP_KERNELVER="$(uname -r)"
     fi
 
-    if ! is_atomic || [ "$(uname -m)" = "s390x" ]; then
-        kdump_bootdir="/boot"
+    read machine_id < /etc/machine-id
+    boot_dirlist=${KDUMP_BOOTDIR:-"/boot /boot/efi /efi /"}
+    boot_imglist="$KDUMP_IMG-$KDUMP_KERNELVER$KDUMP_IMG_EXT $machine_id/$KDUMP_KERNELVER/$KDUMP_IMG"
+
+    # Use BOOT_IMAGE as reference if possible, strip the GRUB root device prefix in (hd0,gpt1) format
+    local boot_img="$(cat /proc/cmdline | sed "s/^BOOT_IMAGE=\((\S*)\)\?\(\S*\) .*/\2/")"
+    if [ -n "$boot_img" ]; then
+        boot_imglist="$boot_img $boot_imglist"
+    fi
+
+    for dir in $boot_dirlist; do
+        for img in $boot_imglist; do
+            if [ -f "$dir/$img" ]; then
+                KDUMP_KERNEL=$(echo $dir/$img | tr -s '/')
+                break 2
+            fi
+        done
+    done
+
+    if ! [ -e "$KDUMP_KERNEL" ]; then
+        echo "Failed to detect kdump kernel location"
+        return 1
+    fi
+
+    # Set KDUMP_BOOTDIR to where kernel image is stored
+    KDUMP_BOOTDIR=$(dirname $KDUMP_KERNEL)
+
+    # Default initrd should just stay aside of kernel image, try to find it in KDUMP_BOOTDIR
+    boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd"
+    for initrd in $boot_initrdlist; do
+        if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then
+            DEFAULT_INITRD="$KDUMP_BOOTDIR/$initrd"
+            break
+        fi
+    done
+
+    # Get kdump initrd from default initrd filename
+    # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img
+    # initrd => initrdkdump
+    if [[ -z "$DEFAULT_INITRD" ]]; then
+        KDUMP_INITRD=${KDUMP_BOOTDIR}/initramfs-${KDUMP_KERNELVER}kdump.img
+    elif [[ $(basename $DEFAULT_INITRD) == *.* ]]; then
+        KDUMP_INITRD=${DEFAULT_INITRD%.*}kdump.${DEFAULT_INITRD##*.}
     else
-        eval $(cat /proc/cmdline| grep "BOOT_IMAGE" | cut -d' ' -f1)
-        kdump_bootdir="/boot"$(dirname $BOOT_IMAGE)
+        KDUMP_INITRD=${DEFAULT_INITRD}kdump
     fi
-    echo $kdump_bootdir
 }
 
 #
@@ -727,13 +782,5 @@ prepare_cmdline()
     if [ ! -z ${id} ] ; then
         cmdline=$(append_cmdline "${cmdline}" disable_cpu_apicid ${id})
     fi
-
-    # Disable efifb if hyperv_fb is in use, hyperv_fb will relocate the framebuffer
-    # but kexec_file_load always use original screen_info and in second kernel efifb
-    # will try to access an invalid framebuffer address
-    if [ -d /sys/module/hyperv_fb ]; then
-        cmdline=$(append_cmdline "$cmdline" "video=efifb:off")
-    fi
-
     echo ${cmdline}
 }
diff --git a/SOURCES/kdump.conf b/SOURCES/kdump.conf
index 76fecd4..689c3e0 100644
--- a/SOURCES/kdump.conf
+++ b/SOURCES/kdump.conf
@@ -62,9 +62,9 @@
 #             as the initrd will automatically be populated with a
 #             config file appropriate for the running kernel.
 #             The default core_collector for raw/ssh dump is:
-#             "makedumpfile -F -l --message-level 1 -d 31".
+#             "makedumpfile -F -l --message-level 7 -d 31".
 #             The default core_collector for other targets is:
-#             "makedumpfile -l --message-level 1 -d 31".
+#             "makedumpfile -l --message-level 7 -d 31".
 #
 #             "makedumpfile -F" will create a flattened vmcore.
 #             You need to use "makedumpfile -R" to rearrange the dump data to
@@ -169,7 +169,7 @@
 #ssh user@my.server.com
 #sshkey /root/.ssh/kdump_id_rsa
 path /var/crash
-core_collector makedumpfile -l --message-level 1 -d 31
+core_collector makedumpfile -l --message-level 7 -d 31
 #core_collector scp
 #kdump_post /var/crash/scripts/kdump-post.sh
 #kdump_pre /var/crash/scripts/kdump-pre.sh
diff --git a/SOURCES/kdump.conf.5 b/SOURCES/kdump.conf.5
index 4aacac8..87fe3af 100644
--- a/SOURCES/kdump.conf.5
+++ b/SOURCES/kdump.conf.5
@@ -85,9 +85,9 @@ for the running kernel.
 .PP
 Note 1: About default core collector:
 The default core_collector for raw/ssh dump is:
-"makedumpfile -F -l --message-level 1 -d 31".
+"makedumpfile -F -l --message-level 7 -d 31".
 The default core_collector for other targets is:
-"makedumpfile -l --message-level 1 -d 31".
+"makedumpfile -l --message-level 7 -d 31".
 Even if core_collector option is commented out in kdump.conf, makedumpfile
 is the default core collector and kdump uses it internally.
 If one does not want makedumpfile as default core_collector, then they
@@ -307,11 +307,11 @@ Above will effectively be translated to:
 cp --sparse=always /proc/vmcore <dest-path>/vmcore
 .TP
 ex2.
-core_collector "makedumpfile -l --message-level 1 -d 31"
+core_collector "makedumpfile -l --message-level 7 -d 31"
 
 Above will effectively be translated to:
 
-makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore
+makedumpfile -l --message-level 7 -d 31 /proc/vmcore <dest-path>/vmcore
 .PP
 For dump targets like raw and ssh, in general, core collector should expect
 one argument (source file) and should output the processed core on standard
@@ -328,11 +328,11 @@ Above will effectively be translated to.
 cat /proc/vmcore | dd of=<target-device>
 .TP
 ex4.
-core_collector "makedumpfile -F -l --message-level 1 -d 31"
+core_collector "makedumpfile -F -l --message-level 7 -d 31"
 
 Above will effectively be translated to.
 
-makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>
+makedumpfile -F -l --message-level 7 -d 31 | dd of=<target-device>
 .PP
 ssh dumps examples
 .TP
@@ -344,11 +344,11 @@ Above will effectively be translated to.
 cat /proc/vmcore | ssh <options> <remote-location> "dd of=path/vmcore"
 .TP
 ex6.
-core_collector "makedumpfile -F -l --message-level 1 -d 31"
+core_collector "makedumpfile -F -l --message-level 7 -d 31"
 
 Above will effectively be translated to.
 
-makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
+makedumpfile -F -l --message-level 7 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
 
 There is one exception to standard output rule for ssh dumps. And that is
 scp. As scp can handle ssh destinations for file transfers, one can
diff --git a/SOURCES/kdump.sysconfig.s390x b/SOURCES/kdump.sysconfig.s390x
index de0ac49..c989897 100644
--- a/SOURCES/kdump.sysconfig.s390x
+++ b/SOURCES/kdump.sysconfig.s390x
@@ -31,7 +31,7 @@ MKDUMPRD_ARGS=""
 #
 # Example:
 #   KEXEC_ARGS="--elf32-core-headers"
-KEXEC_ARGS=""
+KEXEC_ARGS="-s"
 
 #Where to find the boot image
 #KDUMP_BOOTDIR="/boot"
diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl
index b4dbef0..b29e180 100755
--- a/SOURCES/kdumpctl
+++ b/SOURCES/kdumpctl
@@ -2,6 +2,7 @@
 KEXEC=/sbin/kexec
 
 KDUMP_KERNELVER=""
+KDUMP_KERNEL=""
 KDUMP_COMMANDLINE=""
 KEXEC_ARGS=""
 KDUMP_CONFIG_FILE="/etc/kdump.conf"
@@ -13,6 +14,7 @@ INITRD_CHECKSUM_LOCATION="/boot/.fadump_initrd_checksum"
 DUMP_TARGET=""
 DEFAULT_INITRD=""
 DEFAULT_INITRD_BAK=""
+KDUMP_INITRD=""
 TARGET_INITRD=""
 FADUMP_REGISTER_SYS_NODE="/sys/kernel/fadump_registered"
 #kdump shall be the default dump mode
@@ -94,7 +96,7 @@ rebuild_fadump_initrd()
 	# this file tells the initrd is fadump enabled
 	touch /tmp/fadump.initramfs
 	target_initrd_tmp="$TARGET_INITRD.tmp"
-	$MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $kdump_kver \
+	$MKDUMPRD $target_initrd_tmp --rebuild $DEFAULT_INITRD_BAK --kver $KDUMP_KERNELVER \
 		-i /tmp/fadump.initramfs /etc/fadump.initramfs
 	if [ $? != 0 ]; then
 		echo "mkdumprd: failed to rebuild initrd with fadump support" >&2
@@ -118,7 +120,7 @@ check_earlykdump_is_enabled()
 
 rebuild_kdump_initrd()
 {
-	$MKDUMPRD $TARGET_INITRD $kdump_kver
+	$MKDUMPRD $TARGET_INITRD $KDUMP_KERNELVER
 	if [ $? != 0 ]; then
 		echo "mkdumprd: failed to make kdump initrd" >&2
 		return 1
@@ -189,6 +191,10 @@ backup_default_initrd()
 
 restore_default_initrd()
 {
+	if [ ! -f "$DEFAULT_INITRD" ]; then
+		return
+	fi
+
 	# If a backup initrd exists, we must be switching back from
 	# fadump to kdump. Restore the original default initrd.
 	if [ -f $DEFAULT_INITRD_BAK ] && [ -f $INITRD_CHECKSUM_LOCATION ]; then
@@ -211,40 +217,34 @@ restore_default_initrd()
 
 check_config()
 {
-	local nr
-
-	nr=$(awk 'BEGIN{cnt=0} /^raw|^ssh[[:blank:]]|^nfs|^ext[234]|^xfs|^btrfs|^minix|^dracut_args .*\-\-mount/{cnt++} END{print cnt}' $KDUMP_CONFIG_FILE)
-	[ $nr -gt 1 ] && {
-		echo "More than one dump targets specified."
-		return 1
-	}
-
-	nr=$(grep "^dracut_args .*\-\-mount" $KDUMP_CONFIG_FILE | grep -o "\-\-mount" | wc -l)
-	[ $nr -gt 1 ] && {
-		echo "Multiple mount targets specified in one \"dracut_args\"."
-		return 1
-	}
-
-	# Check if we have any leading spaces (or tabs) before the
-	# variable name in the kdump conf file
-	if grep -E -q '^[[:blank:]]+[a-z]' $KDUMP_CONFIG_FILE; then
-		echo "No whitespaces are allowed before a kdump option name in $KDUMP_CONFIG_FILE"
-		return 1
-	fi
-
+	local -A _opt_rec
 	while read config_opt config_val; do
+		if [ -z "$config_val" ]; then
+			echo "Invalid kdump config value for option $config_opt"
+			return 1
+		fi
+
 		case "$config_opt" in
-		\#* | "")
+		dracut_args)
+			if [[ $config_val == *--mount* ]]; then
+				if [ $(echo $config_val | grep -o "\-\-mount" | wc -l) -ne 1 ]; then
+					echo "Multiple mount targets specified in one \"dracut_args\"."
+					return 1
+				fi
+				config_opt=_target
+			fi
 			;;
-		raw|ext2|ext3|ext4|minix|btrfs|xfs|nfs|ssh|sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|dracut_args|fence_kdump_args|fence_kdump_nodes)
-			# remove inline comments after the end of a directive.
-			[ -z "$config_val" ] && {
-				echo "Invalid kdump config value for option $config_opt."
-				return 1;
-			}
-			if [ -d "/proc/device-tree/ibm,opal/dump" ] && [ "$config_opt" == "raw" ]; then
+		raw)
+			if [ -d "/proc/device-tree/ibm,opal/dump" ]; then
 				echo "WARNING: Won't capture opalcore when 'raw' dump target is used."
+				return 1
 			fi
+			config_opt=_target
+			;;
+		ext[234]|minix|btrfs|xfs|nfs|ssh)
+			config_opt=_target
+			;;
+		sshkey|path|core_collector|kdump_post|kdump_pre|extra_bins|extra_modules|failure_action|default|final_action|force_rebuild|force_no_rebuild|fence_kdump_args|fence_kdump_nodes)
 			;;
 		net|options|link_delay|disk_timeout|debug_mem_level|blacklist)
 			echo "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives."
@@ -252,14 +252,23 @@ check_config()
 			;;
 		*)
 			echo "Invalid kdump config option $config_opt"
-			return 1;
+			return 1
 			;;
 		esac
+
+		if [ -n "${_opt_rec[$config_opt]}" ]; then
+			if [ $config_opt == _target ]; then
+				echo "More than one dump targets specified"
+			else
+				echo "Duplicated kdump config value of option $config_opt"
+			fi
+			return 1
+		fi
+		_opt_rec[$config_opt]="$config_val"
 	done <<< "$(read_strip_comments $KDUMP_CONFIG_FILE)"
 
 	check_failure_action_config || return 1
 	check_final_action_config || return 1
-
 	check_fence_kdump_config || return 1
 
 	return 0
@@ -294,18 +303,12 @@ get_pcs_cluster_modified_files()
 
 setup_initrd()
 {
-	KDUMP_BOOTDIR=$(check_boot_dir "${KDUMP_BOOTDIR}")
-
-	if [ -z "$KDUMP_KERNELVER" ]; then
-		kdump_kver=`uname -r`
-	else
-		kdump_kver=$KDUMP_KERNELVER
+	prepare_kdump_bootinfo
+	if [ $? -ne 0 ]; then
+		return 1
 	fi
 
-	kdump_kernel="${KDUMP_BOOTDIR}/${KDUMP_IMG}-${kdump_kver}${KDUMP_IMG_EXT}"
-
-	DEFAULT_INITRD="${KDUMP_BOOTDIR}/initramfs-`uname -r`.img"
-	DEFAULT_INITRD_BAK="${KDUMP_BOOTDIR}/.initramfs-`uname -r`.img.default"
+	DEFAULT_INITRD_BAK="$KDUMP_BOOTDIR/.$(basename $DEFAULT_INITRD).default"
 	if [ $DEFAULT_DUMP_MODE == "fadump" ]; then
 		TARGET_INITRD="$DEFAULT_INITRD"
 		if [ ! -s "$TARGET_INITRD" ]; then
@@ -317,7 +320,7 @@ setup_initrd()
 		# with fadump aware initrd
 		backup_default_initrd
 	else
-		TARGET_INITRD="${KDUMP_BOOTDIR}/initramfs-${kdump_kver}kdump.img"
+		TARGET_INITRD="$KDUMP_INITRD"
 
 		# check if a backup of default initrd exists. If yes,
 		# it signifies a switch from fadump mode. So, restore
@@ -357,25 +360,25 @@ check_files_modified()
 	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
 	CHECK_FILES=`grep ^extra_bins $KDUMP_CONFIG_FILE | cut -d\  -f2-`
 	EXTRA_BINS="$EXTRA_BINS $CHECK_FILES"
-	files="$KDUMP_CONFIG_FILE $kdump_kernel $EXTRA_BINS $CORE_COLLECTOR"
+	files="$KDUMP_CONFIG_FILE $KDUMP_KERNEL $EXTRA_BINS $CORE_COLLECTOR"
 	[[ -e /etc/fstab ]] && files="$files /etc/fstab"
 
 	# Check for any updated extra module
 	EXTRA_MODULES="$(grep ^extra_modules $KDUMP_CONFIG_FILE | sed 's/^extra_modules\s*//')"
 	if [ -n "$EXTRA_MODULES" ]; then
-		if [ -e /lib/modules/$kdump_kver/modules.dep ]; then
-			files="$files /lib/modules/$kdump_kver/modules.dep"
+		if [ -e /lib/modules/$KDUMP_KERNELVER/modules.dep ]; then
+			files="$files /lib/modules/$KDUMP_KERNELVER/modules.dep"
 		fi
 		for _module in $EXTRA_MODULES; do
-			_module_file="$(modinfo --set-version "$kdump_kver" --filename "$_module" 2>/dev/null)"
+			_module_file="$(modinfo --set-version "$KDUMP_KERNELVER" --filename "$_module" 2>/dev/null)"
 			if [[ $? -eq 0 ]]; then
 				files="$files $_module_file"
 				for _dep_modules in $(modinfo -F depends $_module | tr ',' ' '); do
-				    files="$files $(modinfo --set-version "$kdump_kver" --filename $_dep_modules 2>/dev/null)"
+				    files="$files $(modinfo --set-version "$KDUMP_KERNELVER" --filename $_dep_modules 2>/dev/null)"
 				done
 			else
 				# If it's not a module nor builtin, give an error
-				if ! ( modprobe --set-version "$kdump_kver" --dry-run "$_module" &>/dev/null ); then
+				if ! ( modprobe --set-version "$KDUMP_KERNELVER" --dry-run "$_module" &>/dev/null ); then
 					echo "Module $_module not found"
 				fi
 			fi
@@ -419,7 +422,7 @@ check_dump_fs_modified()
 	local _old_dev _old_mntpoint _old_fstype
 	local _new_dev _new_mntpoint _new_fstype
 	local _target _path _dracut_args
-	local _target_drivers _module_name
+	local _target_drivers _module_name _module_filename
 
 	local _old_drivers="$(lsinitrd $TARGET_INITRD -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')"
 
@@ -468,10 +471,10 @@ check_dump_fs_modified()
 
 	check_block_and_slaves_all _record_block_drivers "$(get_maj_min "$_target")"
 	for _driver in $_target_drivers; do
-		# Target is mounted already, if module is not included by current kernel,
-		# could be a deprecated/invalid driver name or a built-in module
-		_module_name=$(modinfo --set-version "$kdump_kver" -F name $_driver 2>/dev/null)
-		if [ $? -ne 0 ] || [ -z "$_module_name" ]; then
+		# Skip deprecated/invalid driver name or built-in module
+		_module_name=$(modinfo --set-version "$KDUMP_KERNELVER" -F name $_driver 2>/dev/null)
+		_module_filename=$(modinfo --set-version "$KDUMP_KERNELVER" -n $_driver 2>/dev/null)
+		if [ $? -ne 0 ] || [ -z "$_module_name" ] || [[ "$_module_filename" = *"(builtin)"* ]]; then
 			continue
 		fi
 		if ! [[ " $_old_drivers " == *" $_module_name "* ]]; then
@@ -537,7 +540,7 @@ check_wdt_modified()
 		# modalias. Currently load all of them.
 		# TODO: Need to find a way to avoid any unwanted module
 		# represented by modalias
-		_wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null)
+		_wdtdrv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_wdtdrv 2>/dev/null)
 		if [[ $_wdtdrv ]]; then
 			for i in $_wdtdrv; do
 				_drivers[$i]=1
@@ -552,7 +555,7 @@ check_wdt_modified()
 			[[ -f "$_wdtppath/modalias" ]] || continue
 
 			_wdtdrv=$(< "$_wdtppath/modalias")
-			_wdtdrv=$(modprobe --set-version "$kdump_kver" -R $_wdtdrv 2>/dev/null)
+			_wdtdrv=$(modprobe --set-version "$KDUMP_KERNELVER" -R $_wdtdrv 2>/dev/null)
 			if [[ $_wdtdrv ]]; then
 				for i in $_wdtdrv; do
 					_drivers[$i]=1
@@ -697,7 +700,7 @@ load_kdump()
 
 	$KEXEC $KEXEC_ARGS $standard_kexec_args \
 		--command-line="$KDUMP_COMMANDLINE" \
-		--initrd=$TARGET_INITRD $kdump_kernel
+		--initrd=$TARGET_INITRD $KDUMP_KERNEL
 	if [ $? == 0 ]; then
 		echo "kexec: loaded kdump kernel"
 		return 0
diff --git a/SOURCES/kexec-kdump-howto.txt b/SOURCES/kexec-kdump-howto.txt
index 50bd316..23021d8 100644
--- a/SOURCES/kexec-kdump-howto.txt
+++ b/SOURCES/kexec-kdump-howto.txt
@@ -613,7 +613,7 @@ is a dump filtering and compression utility provided with kexec-tools. On
 some architectures, it can drastically reduce the size of your vmcore files,
 which becomes very useful on systems with large amounts of memory.
 
-A typical setup is 'core_collector makedumpfile -F -l --message-level 1 -d 31',
+A typical setup is 'core_collector makedumpfile -F -l --message-level 7 -d 31',
 but check the output of '/sbin/makedumpfile --help' for a list of all available
 options (-i and -g don't need to be specified, they're automatically taken care
 of). Note that use of makedumpfile requires that the kernel-debuginfo package
@@ -633,11 +633,11 @@ First one is source file and second one is target file. For ex.
 
 - ex2.
 
-  core_collector "makedumpfile -l --message-level 1 -d 31"
+  core_collector "makedumpfile -l --message-level 7 -d 31"
 
   Above will effectively be translated to:
 
-  makedumpfile -l --message-level 1 -d 31 /proc/vmcore <dest-path>/vmcore
+  makedumpfile -l --message-level 7 -d 31 /proc/vmcore <dest-path>/vmcore
 
 For dump targets like raw and ssh, in general, core collector should expect
 one argument (source file) and should output the processed core on standard
@@ -656,11 +656,11 @@ raw dumps core_collector examples:
 
 - ex4.
 
-  core_collector "makedumpfile -F -l --message-level 1 -d 31"
+  core_collector "makedumpfile -F -l --message-level 7 -d 31"
 
   Above will effectively be translated to.
 
-  makedumpfile -F -l --message-level 1 -d 31 | dd of=<target-device>
+  makedumpfile -F -l --message-level 7 -d 31 | dd of=<target-device>
 
 ssh dumps core_collector examples:
 
@@ -674,11 +674,11 @@ ssh dumps core_collector examples:
 
 - ex6.
 
-  core_collector "makedumpfile -F -l --message-level 1 -d 31"
+  core_collector "makedumpfile -F -l --message-level 7 -d 31"
 
   Above will effectively be translated to.
 
-  makedumpfile -F -l --message-level 1 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
+  makedumpfile -F -l --message-level 7 -d 31 | ssh <options> <remote-location> "dd of=path/vmcore"
 
 There is one exception to standard output rule for ssh dumps. And that is
 scp. As scp can handle ssh destinations for file transfers, one can
@@ -696,9 +696,9 @@ About default core collector
 ----------------------------
 
 Default core_collector for ssh/raw dump is:
-"makedumpfile -F -l --message-level 1 -d 31".
+"makedumpfile -F -l --message-level 7 -d 31".
 Default core_collector for other targets is:
-"makedumpfile -l --message-level 1 -d 31".
+"makedumpfile -l --message-level 7 -d 31".
 
 Even if core_collector option is commented out in kdump.conf, makedumpfile
 is default core collector and kdump uses it internally.
diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec
index c04f1fc..b5b638f 100644
--- a/SPECS/kexec-tools.spec
+++ b/SPECS/kexec-tools.spec
@@ -1,6 +1,6 @@
 Name: kexec-tools
 Version: 2.0.20
-Release: 34%{?dist}
+Release: 35%{?dist}
 License: GPLv2
 Group: Applications/System
 Summary: The kexec/kdump userspace component
@@ -34,6 +34,7 @@ Source28: supported-kdump-targets.txt
 Source29: kdump-udev-throttler
 Source30: kdump.sysconfig.aarch64
 Source31: fadump-howto.txt
+Source32: 60-kdump.install
 
 #######################################
 # These are sources for mkdumpramfs
@@ -230,6 +231,8 @@ install -m 755 %{SOURCE29} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttl
 install -m 644 %{SOURCE15} $RPM_BUILD_ROOT%{_mandir}/man5/kdump.conf.5
 install -m 644 %{SOURCE16} $RPM_BUILD_ROOT%{_unitdir}/kdump.service
 install -m 755 -D %{SOURCE22} $RPM_BUILD_ROOT%{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh
+install -m 755 -D %{SOURCE30} $RPM_BUILD_ROOT%{_prefix}/lib/kernel/install.d/60-kdump.install
+
 
 %ifarch %{ix86} x86_64 ppc64 s390x ppc64le aarch64
 install -m 755 makedumpfile-1.6.7/makedumpfile $RPM_BUILD_ROOT/usr/sbin/makedumpfile
@@ -366,6 +369,7 @@ done
 %{_mandir}/man5/*
 %{_unitdir}/kdump.service
 %{_prefix}/lib/systemd/system-generators/kdump-dep-generator.sh
+%{_prefix}/lib/kernel/install.d/60-kdump.install
 %doc News
 %license COPYING
 %doc TODO
@@ -381,6 +385,23 @@ done
 %endif
 
 %changelog
+* Fri Oct 30 2020 Pingfan Liu <piliu@redhat.com> - 2.0.20-35
+- module-setup.sh: Instead of drop journalctl log, just don't read kmsg
+- s390x: enable the kexec file load by default
+- increase makdumpfile default message level to 7
+- Rework check_config and warn on any duplicated option
+- kdumpctl: Error out if path is set more than once.
+- Don't drop journalctl content if failure action is "shell"
+- dracut-module-install: Move systemd conf install code to a function
+- kdump-lib.sh: Remove is_atomic
+- Refactor kernel image and initrd detection code
+- early-kdump: Use consistent symbol link for kernel and initramfs
+- kdump-lib: strip grub device from kdump_bootdir
+- kdumpctl: fix driver change detection on latest Fedora
+- Revert "kdump-lib: disable efifb if hyperv_fb is in use"
+- kdump-lib.sh: detect secure boot on s390
+- Add a kernel install hook to clean up kdump initramfs
+
 * Wed Aug 19 2020 Pingfan Liu <piliu@redhat.com> - 2.0.20-34
 - kdump-lib: disable efifb if hyperv_fb is in use