#!/bin/sh

# This small shell script sets various iDRAC configuration
# so that the serial console can work by default.

set -e
set -x

PRODUCT_NAME=$(dmidecode -s system-product-name)

if [ "${PRODUCT_NAME}" = "PowerEdge R410" ] || [ "${PRODUCT_NAME}" = "PowerEdge R610" ] ; then
	# This fixes a security problem on this type of hardware, where it's possible
	# otherwise to create an IPMI user without being authenticated.
	ipmitool lan set 1 cipher_privs Xaaaaaaaaaaaaaa
	IPMI_TYPE=iDRAC6
else
	IPMI_TYPE=$(ipmitool sdr elist mcloc | awk '{print $1}')
fi

if ! [ -x /usr/bin/racadm ] ; then
	exit 0
else
	RACADM=/usr/bin/racadm
fi

JOB=no

# Param: $1 = key category to change
#        $2 = key in the cat
#        $3 = value to use
# Return: $JOB is set to "yes" if the value changed
set_value_with_job () {
	local CAT_NAME CAT_ENTRY VAL
	CAT_NAME=${1}
	CAT_ENTRY=${2}
	CAT_VAL=${3}

	CUR_VAL=$(${RACADM} get ${CAT_NAME}.${CAT_ENTRY} | grep ${CAT_ENTRY} | cut -d= -f2)
	if [ "${CUR_VAL}" != "${CAT_VAL}" ] ; then
		${RACADM} set ${CAT_NAME}.${CAT_ENTRY} ${CAT_VAL}
		JOB=yes
	fi
}

if [ "${IPMI_TYPE}" = "iDRAC6" ] || [ "${IPMI_TYPE}" = "iDRAC7" ] || [ "${IPMI_TYPE}" = "iDRAC8" ] || [ "${IPMI_TYPE}" = "iDRAC9" ] ; then

	if [ "${IPMI_TYPE}" = "iDRAC6" ] || [ "${IPMI_TYPE}" = "iDRAC7" ] ; then
		${RACADM} config -g cfgLanNetworking -o cfgDNSDomainNameFromDHCP 0
		${RACADM} config -g cfgIpmiLan -o cfgIpmiLanEnable 1

		${RACADM} config -g cfgNetTuning -o cfgNetTuningNicAutoneg 1
		${RACADM} config -g cfgNetTuning -o cfgNetTuningNicFullDuplex 1
		${RACADM} config -g cfgNetTuning -o cfgNetTuningNicMtu 1500

		# Serial over LAN config setup
		${RACADM} config -g cfgUserAdmin -o cfgUserAdminSolEnable 1 -i 2
		${RACADM} config -g cfgSerial -o cfgSerialBaudRate 115200
		${RACADM} config -g cfgSerial -o cfgSerialConsoleEnable 1
		${RACADM} config -g cfgSerial -o cfgSerialConsoleIdleTimeout 0
		${RACADM} config -g cfgSerial -o cfgSerialConsoleNoAuth 1
		${RACADM} config -g cfgSerial -o cfgSerialSshEnable 1
		${RACADM} config -g cfgSerial -o cfgSerialCom2RedirEnable 1
		${RACADM} config -g cfgIpmiSol -o cfgIpmiSolEnable 1
		${RACADM} config -g cfgIpmiSol -o cfgIpmiSolBaudRate 115200
		${RACADM} config -g cfgIpmiSerial -o cfgIpmiSerialBaudRate 115200
		${RACADM} config -g cfgIpmiSerial -o cfgIpmiSerialConnectionMode 1
		${RACADM} config -g cfgIpmiSerial -o cfgIpmiSerialHandshakeControl 1

		# Activate the web interface:
		${RACADM} config -g cfgRacTuning -o cfgRacTuneWebserverEnable 1
		${RACADM} config -g cfgRacTuning -o cfgRacTuneRemoteRacadmEnable 1
		${RACADM} config -g cfgRacTuning -o cfgRacTuneVirtualConsoleAuthorizeMultipleSessions 1

		# First boot device
		#${RACADM} config -g cfgServerInfo -o cfgServerFirstBootDevice PXE
	else
		# Make sure the user 2 is activated
		${RACADM} set iDRAC.Users.2.Enable Enabled

		# Various general BIOS settings
		set_value_with_job BIOS.SysSecurity AcPwrRcvry On

		# IPMI ip configuration
		${RACADM} set iDRAC.IPv4.DHCPEnable Disabled
		${RACADM} set iDRAC.IPv4.DNSFromDHCP Disabled
		${RACADM} set iDRAC.IPv4.Enable Enabled
		${RACADM} set iDRAC.IPv4Static.DNSFromDHCP Disabled

		# IPMI NIC configuration
		${RACADM} set iDRAC.NIC.Failover All
		${RACADM} set iDRAC.NIC.Enable Enabled
		${RACADM} set iDRAC.IPMILan.Enable Enabled

		# Sensitive defaults
#		${RACADM} set BIOS.BiosBootSettings.HddSeq Disk.USBBack.1-1,RAID.Integrated.1-1
		set_value_with_job BIOS.BiosBootSettings HddFailover Enabled
		set_value_with_job BIOS.BiosBootSettings BootSeqRetry Enabled
		if ! [ "${PRODUCT_NAME}" = "PowerEdge R6525" ] ; then
			set_value_with_job BIOS.IntegratedDevices IoatEngine Enabled
		fi
		set_value_with_job BIOS.IntegratedDevices SriovGlobalEnable Enabled
#		${RACADM} jobqueue create BIOS.Setup.1-1

		# Default is GMT+5 (ie: us east coast), let's fix this
		${RACADM} set iDRAC.Time.Timezone UTC

		# IPMI serial config
		${RACADM} set BIOS.SerialCommSettings.RedirAfterBoot Enabled

		set_value_with_job BIOS.SerialCommSettings ConTermType Vt100Vt220
		if [ "${PRODUCT_NAME}" = "PowerEdge R6525" ] ; then
			set_value_with_job BIOS.SerialCommSettings SerialPortAddress Com2
#			set_value_with_job BIOS.SerialCommSettings.SerialComm OnConRedirAuto
		else
			set_value_with_job BIOS.SerialCommSettings ExtSerialConnector Serial1
			set_value_with_job BIOS.SerialCommSettings SerialComm OnConRedirCom2
			set_value_with_job BIOS.SerialCommSettings SerialPortAddress Serial1Com1Serial2Com2
		fi

		set_value_with_job BIOS.SysSecurity AcPwrRcvry On
		set_value_with_job BIOS.SysProfileSettings SysProfile PerfOptimized
		set_value_with_job BIOS.MiscSettings ErrPrompt Disabled
		set_value_with_job BIOS.IntegratedDevices PcieEnhancedPreferredIo Enabled

		# Disable embedded network cards in these machines,
		# as it gets on the way for proper boot on additional PCI
		# cards (like Mellanox Connect-X 5)
		if [ "${PRODUCT_NAME}" = "PowerEdge R6525" ] ; then
			set_value_with_job BIOS.IntegratedDevices EmbNic1Nic2 DisabledOs
		fi

		${RACADM} set iDRAC.IPMISerial.BaudRate 115200 || true
		${RACADM} set iDRAC.IPMISerial.FlowControl RTS/CTS || true
		${RACADM} set iDRAC.IPMISerial.HandshakeControl Enabled || true
		${RACADM} set iDRAC.IPMISOL.BaudRate 115200 || true
		${RACADM} set iDRAC.IPMISOL.Enable Enabled || true
		${RACADM} set iDRAC.Serial.BaudRate 115200 || true
		${RACADM} set iDRAC.Serial.Enable Enabled || true
		${RACADM} set iDRAC.SerialRedirection.Enable Enabled || true

		# Enable the WEB interface
		${RACADM} set iDRAC.WebServer.Enable Enabled || true

		# SATA settings
		set_value_with_job BIOS.SataSettings EmbSata AhciMode

		# NUMA Node Per Socket (NPS):
		if [ "${PRODUCT_NAME}" = "PowerEdge R6525" ] || [ "${PRODUCT_NAME}" = "PowerEdge R7525" ]; then
			CPU_MODEL=$(lscpu | grep "Model name:" | sed -e 's/Model name://')
			if echo "${CPU_MODEL}" | grep -q "AMD EPYC" ; then
				AMD_CPU_NAME=$(echo "${CPU_MODEL}" | sed -e 's/AMD EPYC //' | awk '{print $1}')
				case "${AMD_CPU_NAME}" in
				7H12|7F32|7F52|7262|7302|7352|7402|7452|7502|7532|7542|7642|7662|7702|7742)
					NUMA_NPS=4
				;;
				7F72|7552)
					NUMA_NPS=2
				;;
				7252|7272|7282)
					NUMA_NPS=1
				;;
				*)
				;;
				esac
				set_value_with_job BIOS.ProcSettings NumaNodesPerSocket ${NUMA_NPS}
			fi
		fi

		# Some CPU settings
		set_value_with_job BIOS.ProcSettings ProcVirtualization Enabled
		if [ "${PRODUCT_NAME}" = "PowerEdge R6525" ] ; then
			echo "No BIOS.ProcSettings.ProcAdjCacheLine in PowerEdge R6525"
		else
			set_value_with_job BIOS.ProcSettings ProcAdjCacheLine Enabled
		fi
		if [ "${JOB}" = "yes" ] ; then
			# This creates a job on next reboot, as some settings needs this.
			${RACADM} jobqueue create BIOS.Setup.1-1
		fi
	fi
fi

exit 0
