Files
Synology_enable_eunit/syno_enable_eunit.sh
Dave Russell 156b0cd93a Update syno_enable_eunit.sh
v3.0.19
- Bug fix when --unit option used (introduced in v3.0.18).
2024-10-05 12:45:28 +10:00

1117 lines
32 KiB
Bash

#!/usr/bin/env bash
#-----------------------------------------------------------------------------------
# Enable Expansion Units in Synology NAS that don't officially support them.
#
# Allows using your Synology expansion unit
# in Synology NAS models that aren't on their supported model list.
#
# Github: https://github.com/007revad/Synology_enable_eunit
# Script verified at https://www.shellcheck.net/
#
# To run in a shell (replace /volume1/scripts/ with path to script):
# sudo -i /volume1/scripts/syno_enable_eunit.sh
#-----------------------------------------------------------------------------------
scriptver="v3.0.19"
script=Synology_enable_eunit
repo="007revad/Synology_enable_eunit"
scriptname=syno_enable_eunit
# Check BASH variable is bash
if [ ! "$(basename "$BASH")" = bash ]; then
echo "This is a bash script. Do not run it with $(basename "$BASH")"
printf \\a
exit 1 # Not running in bash
fi
# Check script is running on a Synology NAS
if ! /usr/bin/uname -a | grep -q -i synology; then
echo "This script is NOT running on a Synology NAS!"
echo "Copy the script to a folder on the Synology"
echo "and run it from there."
exit 1 # Not Synology NAS
fi
ding(){
printf \\a
}
usage(){
cat <<EOF
$script $scriptver - by 007revad
Usage: $(basename "$0") [options]
Options:
-c, --check Check expansion units status
-r, --restore Restore from backups to undo changes
--unit=EUNIT Automatically enable specified expansion unit
Only needed when script is scheduled
EUNIT is dx517, dx513, dx213, dx510, rx418, rx415,
rx410, rx1217rp, rx1217, rx1214r, rx1214, rxX1211rp,
rx1211, dx1215ii, dx1215 or dx1211
-e, --email Disable colored text in output scheduler emails
--autoupdate=AGE Auto update script (useful when script is scheduled)
AGE is how many days old a release must be before
auto-updating. AGE must be a number: 0 or greater
-h, --help Show this help message
-v, --version Show the script version
EOF
exit 0
}
scriptversion(){
cat <<EOF
$script $scriptver - by 007revad
See https://github.com/$repo
EOF
exit 0
}
# Save options used for getopt
args=("$@")
autoupdate=""
# Check for flags with getopt
if options="$(getopt -o abcdefghijklmnopqrstuvwxyz0123456789 -l \
check,restore,unit:,help,version,email,autoupdate:,log,debug -- "${args[@]}")"; then
eval set -- "$options"
while true; do
case "${1,,}" in
-h|--help) # Show usage options
usage
;;
-v|--version) # Show script version
scriptversion
;;
-l|--log) # Log
#log=yes
;;
-d|--debug) # Show and log debug info
debug=yes
;;
-c|--check) # Check current settings
check=yes
break
;;
-r|--restore) # Restore original settings
restore=yes
break
;;
--unit) # Specify eunit to enable for task scheduler
if [[ ${2,,} =~ ^(d|r)x[0-9]+(rp|ii)?$ ]]; then
if [[ ${2:(-2)} == "rp" ]]; then
# Convert to upper case except rp at end
unit="$(b=${2:0:-2} && echo -n "${b^^}")rp"
else
# Convert to upper case
unit="${2^^}"
fi
else
echo -e "Invalid argument '$2'\n"
exit 2 # Invalid argument
fi
shift
;;
-e|--email) # Disable colour text in task scheduler emails
color=no
;;
--autoupdate) # Auto update script
autoupdate=yes
if [[ $2 =~ ^[0-9]+$ ]]; then
delay="$2"
shift
else
delay="0"
fi
;;
--)
shift
break
;;
*) # Show usage options
echo -e "Invalid option '$1'\n"
usage "$1"
;;
esac
shift
done
else
echo
usage
fi
if [[ $debug == "yes" ]]; then
set -x
export PS4='`[[ $? == 0 ]] || echo "\e[1;31;40m($?)\e[m\n "`:.$LINENO:'
fi
# Shell Colors
if [[ $color != "no" ]]; then
#Black='\e[0;30m' # ${Black}
#Red='\e[0;31m' # ${Red}
#Green='\e[0;32m' # ${Green}
Yellow='\e[0;33m' # ${Yellow}
#Blue='\e[0;34m' # ${Blue}
#Purple='\e[0;35m' # ${Purple}
Cyan='\e[0;36m' # ${Cyan}
#White='\e[0;37m' # ${White}
Error='\e[41m' # ${Error}
Off='\e[0m' # ${Off}
else
echo "" # For task scheduler email readability
fi
# Check script is running as root
if [[ $( whoami ) != "root" ]]; then
ding
echo -e "${Error}ERROR${Off} This script must be run as sudo or root!"
exit 1 # Not running as sudo or root
fi
# Get DSM major and minor versions
#dsm=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION majorversion)
#dsminor=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION minorversion)
#if [[ $dsm -gt "6" ]] && [[ $dsminor -gt "1" ]]; then
# dsm72="yes"
#fi
#if [[ $dsm -gt "6" ]] && [[ $dsminor -gt "0" ]]; then
# dsm71="yes"
#fi
# Get NAS model
model=$(cat /proc/sys/kernel/syno_hw_version)
#modelname="$model"
# Show script version
#echo -e "$script $scriptver\ngithub.com/$repo\n"
echo "$script $scriptver"
# Get DSM full version
productversion=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION productversion)
buildphase=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildphase)
buildnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION buildnumber)
smallfixnumber=$(/usr/syno/bin/synogetkeyvalue /etc.defaults/VERSION smallfixnumber)
# Show DSM full version and model
if [[ $buildphase == GM ]]; then buildphase=""; fi
if [[ $smallfixnumber -gt "0" ]]; then smallfix="-$smallfixnumber"; fi
echo -e "$model DSM $productversion-$buildnumber$smallfix $buildphase\n"
# Get StorageManager version
storagemgrver=$(/usr/syno/bin/synopkg version StorageManager)
# Show StorageManager version
if [[ $storagemgrver ]]; then echo -e "StorageManager $storagemgrver\n"; fi
# Show options used
if [[ ${#args[@]} -gt "0" ]]; then
echo "Using options: ${args[*]}"
fi
# Check Synology has a expansion port
# eSATA and InfiniBand ports both appear in syno_slot_mapping as:
# Esata port count: 1
# Eunit port 1 - RX1214
if which syno_slot_mapping >/dev/null; then
esata_ports=$(syno_slot_mapping | grep 'Esata port count' | awk '{print $4}')
if [[ $esata_ports -lt "1" ]]; then
echo -e "${Error}ERROR${Off} Synology NAS has no expansion port(s)!"
exit 1 # No expansion port(s)
fi
else
echo -e "${Error}ERROR${Off} Unsupported Synology NAS model. No syno_slot_mapping command!"
exit 1 # No syno_slot_mapping file
fi
#------------------------------------------------------------------------------
# Check latest release with GitHub API
syslog_set(){
if [[ ${1,,} == "info" ]] || [[ ${1,,} == "warn" ]] || [[ ${1,,} == "err" ]]; then
if [[ $autoupdate == "yes" ]]; then
# Add entry to Synology system log
/usr/syno/bin/synologset1 sys "$1" 0x11100000 "$2"
fi
fi
}
# Get latest release info
# Curl timeout options:
# https://unix.stackexchange.com/questions/94604/does-curl-have-a-timeout
release=$(curl --silent -m 10 --connect-timeout 5 \
"https://api.github.com/repos/$repo/releases/latest")
# Release version
tag=$(echo "$release" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
shorttag="${tag:1}"
# Release published date
published=$(echo "$release" | grep '"published_at":' | sed -E 's/.*"([^"]+)".*/\1/')
published="${published:0:10}"
published=$(date -d "$published" '+%s')
# Today's date
now=$(date '+%s')
# Days since release published
age=$(((now - published)/(60*60*24)))
# Get script location
# https://stackoverflow.com/questions/59895/
source=${BASH_SOURCE[0]}
while [ -L "$source" ]; do # Resolve $source until the file is no longer a symlink
scriptpath=$( cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd )
source=$(readlink "$source")
# If $source was a relative symlink, we need to resolve it
# relative to the path where the symlink file was located
[[ $source != /* ]] && source=$scriptpath/$source
done
scriptpath=$( cd -P "$( dirname "$source" )" >/dev/null 2>&1 && pwd )
scriptfile=$( basename -- "$source" )
echo -e "Running from: ${scriptpath}/$scriptfile\n"
# Warn if script located on M.2 drive
scriptvol=$(echo "$scriptpath" | cut -d"/" -f2)
vg=$(lvdisplay | grep /volume_"${scriptvol#volume}" | cut -d"/" -f3)
md=$(pvdisplay | grep -B 1 -E '[ ]'"$vg" | grep /dev/ | cut -d"/" -f3)
if grep "$md" /proc/mdstat | grep -q nvme; then
echo -e "${Yellow}WARNING${Off} Don't store this script on an NVMe volume!"
fi
cleanup_tmp(){
cleanup_err=
# Delete downloaded .tar.gz file
if [[ -f "/tmp/$script-$shorttag.tar.gz" ]]; then
if ! rm "/tmp/$script-$shorttag.tar.gz"; then
echo -e "${Error}ERROR${Off} Failed to delete"\
"downloaded /tmp/$script-$shorttag.tar.gz!" >&2
cleanup_err=1
fi
fi
# Delete extracted tmp files
if [[ -d "/tmp/$script-$shorttag" ]]; then
if ! rm -r "/tmp/$script-$shorttag"; then
echo -e "${Error}ERROR${Off} Failed to delete"\
"downloaded /tmp/$script-$shorttag!" >&2
cleanup_err=1
fi
fi
# Add warning to DSM log
if [[ $cleanup_err ]]; then
syslog_set warn "$script update failed to delete tmp files"
fi
}
if ! printf "%s\n%s\n" "$tag" "$scriptver" |
sort --check=quiet --version-sort >/dev/null ; then
echo -e "\n${Cyan}There is a newer version of this script available.${Off}"
echo -e "Current version: ${scriptver}\nLatest version: $tag"
scriptdl="$scriptpath/$script-$shorttag"
if [[ -f ${scriptdl}.tar.gz ]] || [[ -f ${scriptdl}.zip ]]; then
# They have the latest version tar.gz downloaded but are using older version
echo "You have the latest version downloaded but are using an older version"
sleep 10
elif [[ -d $scriptdl ]]; then
# They have the latest version extracted but are using older version
echo "You have the latest version extracted but are using an older version"
sleep 10
else
if [[ $autoupdate == "yes" ]]; then
if [[ $age -gt "$delay" ]] || [[ $age -eq "$delay" ]]; then
echo "Downloading $tag"
reply=y
else
echo "Skipping as $tag is less than $delay days old."
fi
else
echo -e "${Cyan}Do you want to download $tag now?${Off} [y/n]"
read -r -t 30 reply
fi
if [[ ${reply,,} == "y" ]]; then
# Delete previously downloaded .tar.gz file and extracted tmp files
cleanup_tmp
if cd /tmp; then
url="https://github.com/$repo/archive/refs/tags/$tag.tar.gz"
if ! curl -JLO -m 30 --connect-timeout 5 "$url"; then
echo -e "${Error}ERROR${Off} Failed to download"\
"$script-$shorttag.tar.gz!"
syslog_set warn "$script $tag failed to download"
else
if [[ -f /tmp/$script-$shorttag.tar.gz ]]; then
# Extract tar file to /tmp/<script-name>
if ! tar -xf "/tmp/$script-$shorttag.tar.gz" -C "/tmp"; then
echo -e "${Error}ERROR${Off} Failed to"\
"extract $script-$shorttag.tar.gz!"
syslog_set warn "$script failed to extract $script-$shorttag.tar.gz!"
else
# Set script sh files as executable
if ! chmod a+x "/tmp/$script-$shorttag/"*.sh ; then
permerr=1
echo -e "${Error}ERROR${Off} Failed to set executable permissions"
syslog_set warn "$script failed to set permissions on $tag"
fi
# Copy new script sh file to script location
if ! cp -p "/tmp/$script-$shorttag/${scriptname}.sh" "${scriptpath}/${scriptfile}";
then
copyerr=1
echo -e "${Error}ERROR${Off} Failed to copy"\
"$script-$shorttag sh file(s) to:\n $scriptpath/${scriptfile}"
syslog_set warn "$script failed to copy $tag to script location"
fi
# Copy new CHANGES.txt file to script location (if script on a volume)
if [[ $scriptpath =~ /volume* ]]; then
# Set permissions on CHANGES.txt
if ! chmod 664 "/tmp/$script-$shorttag/CHANGES.txt"; then
permerr=1
echo -e "${Error}ERROR${Off} Failed to set permissions on:"
echo "$scriptpath/CHANGES.txt"
fi
# Copy new CHANGES.txt file to script location
if ! cp -p "/tmp/$script-$shorttag/CHANGES.txt"\
"${scriptpath}/${scriptname}_CHANGES.txt";
then
if [[ $autoupdate != "yes" ]]; then copyerr=1; fi
echo -e "${Error}ERROR${Off} Failed to copy"\
"$script-$shorttag/CHANGES.txt to:\n $scriptpath"
else
changestxt=" and changes.txt"
fi
fi
# Delete downloaded tmp files
cleanup_tmp
# Notify of success (if there were no errors)
if [[ $copyerr != 1 ]] && [[ $permerr != 1 ]]; then
echo -e "\n$tag ${scriptfile}$changestxt downloaded to: ${scriptpath}\n"
syslog_set info "$script successfully updated to $tag"
# Reload script
printf -- '-%.0s' {1..79}; echo # print 79 -
exec "${scriptpath}/$scriptfile" "${args[@]}"
else
syslog_set warn "$script update to $tag had errors"
fi
fi
else
echo -e "${Error}ERROR${Off}"\
"/tmp/$script-$shorttag.tar.gz not found!"
syslog_set warn "/tmp/$script-$shorttag.tar.gz not found"
fi
fi
cd "$scriptpath" || echo -e "${Error}ERROR${Off} Failed to cd to script location!"
else
echo -e "${Error}ERROR${Off} Failed to cd to /tmp!"
syslog_set warn "$script update failed to cd to /tmp"
fi
fi
fi
fi
#------------------------------------------------------------------------------
# Show connected expansion units
#found_eunits=($(syno_slot_mapping | grep 'Eunit port' | awk '{print $NF}'))
read -r -a found_eunits <<< "$(syno_slot_mapping | grep 'Eunit port' | awk '{print $NF}')"
echo "Connected Expansion Units:"
if [[ ${#found_eunits[@]} -gt "0" ]]; then
for e in "${found_eunits[@]}"; do
echo -e "${Cyan}$e${Off}"
done
else
echo -e "${Cyan}None${Off}"
fi
#echo ""
#------------------------------------------------------------------------------
# Set file variables
if [[ -f /etc.defaults/model.dtb ]]; then # Is device tree model
# Get syn_hw_revision, r1 or r2 etc (or just a linefeed if not a revision)
hwrevision=$(cat /proc/sys/kernel/syno_hw_revision)
# If syno_hw_revision is r1 or r2 it's a real Synology,
# and I need to edit model_rN.dtb instead of model.dtb
if [[ $hwrevision =~ r[0-9] ]]; then
hwrev="_$hwrevision"
fi
dtb_file="/etc.defaults/model${hwrev}.dtb"
dtb2_file="/etc/model${hwrev}.dtb"
#dts_file="/etc.defaults/model${hwrev}.dts"
dts_file="/tmp/model${hwrev}.dts"
else
echo -e "${Error}ERROR${Off} Unsupported Synology NAS model. No model.dtb file!"
exit 1 # No model.dtb file
fi
synoinfo="/etc.defaults/synoinfo.conf"
synoinfo2="/etc/synoinfo.conf"
scemd="/usr/syno/bin/scemd"
rebootmsg(){
# Ensure newly connected ebox is in /var/log/diskprediction log.
# Otherwise the new /var/log/diskprediction log is only created a midnight.
/usr/syno/bin/syno_disk_data_collector record
# Reboot prompt
echo -e "\n${Cyan}The Synology needs to restart.${Off}"
echo -e "Type ${Cyan}yes${Off} to reboot now."
echo -e "Type anything else to quit (if you will restart it yourself)."
read -r -t 10 answer
if [[ ${answer,,} != "yes" ]]; then
echo ""
exit
fi
# # Reboot in the background so user can see DSM's "going down" message
# reboot &
if [[ -x /usr/syno/sbin/synopoweroff ]]; then
/usr/syno/sbin/synopoweroff -r || reboot
else
reboot
fi
}
#------------------------------------------------------------------------------
# Restore changes from backups
compare_md5(){
# $1 is file 1
# $2 is file 2
if [[ -f "$1" ]] && [[ -f "$2" ]]; then
if [[ $(md5sum -b "$1" | awk '{print $1}') == $(md5sum -b "$2" | awk '{print $1}') ]];
then
return 0
else
return 1
fi
else
restoreerr=$((restoreerr+1))
return 2
fi
}
restore_orig(){
restoreerr="0"
if [[ -f ${dtb_file}.bak ]] || [[ -f ${synoinfo}.bak ]] || [[ -f ${scemd}.bak ]] ;
then
# Restore synoinfo.conf from backup
# /usr/syno/etc.defaults/synoinfo.conf
if [[ -f ${synoinfo}.bak ]]; then
setting="$(/usr/syno/bin/synogetkeyvalue "${synoinfo}.bak" support_ew_20_eunit)"
setting2="$(/usr/syno/bin/synogetkeyvalue "${synoinfo}" support_ew_20_eunit)"
if [[ $setting != "$setting2" ]]; then
if /usr/syno/bin/synosetkeyvalue "$synoinfo" support_ew_20_eunit "$setting"; then
/usr/syno/bin/synosetkeyvalue "$synoinfo2" support_ew_20_eunit "$setting"
echo -e "Restored ${synoinfo}"
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} Failed to restore ${synoinfo}!\n"
fi
fi
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} No backup to restore ${synoinfo} from!\n"
fi
# Restore scemd from backup
if [[ -f ${scemd}.bak ]]; then
if compare_md5 "${scemd}".bak "${scemd}"; then
echo -e "${Cyan}OK${Off} ${scemd}"
else
/usr/bin/systemctl stop scemd.service
if cp -p --force "${scemd}.bak" "${scemd}"; then
echo -e "Restored ${scemd}"
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} Failed to restore ${scemd}!\n"
fi
/usr/bin/systemctl start scemd.service
fi
#else
# restoreerr=$((restoreerr+1))
# echo -e "${Error}ERROR${Off} No backup to restore ${scemd} from!\n"
fi
# Restore model.dtb from backup
if [[ -f ${dtb_file}.bak ]]; then
# /etc.default/model.dtb
if compare_md5 "${dtb_file}.bak" "${dtb_file}"; then
echo -e "${Cyan}OK${Off} ${dtb_file}"
else
if cp -p --force "${dtb_file}.bak" "${dtb_file}"; then
echo -e "Restored ${dtb_file}"
reboot=yes
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} Failed to restore ${dtb_file}!\n"
fi
fi
# Restore /etc/model.dtb from /etc.default/model.dtb
if compare_md5 "${dtb_file}.bak" "${dtb2_file}"; then
echo -e "${Cyan}OK${Off} ${dtb2_file}"
else
if cp -p --force "${dtb_file}.bak" "${dtb2_file}"; then
echo -e "Restored ${dtb2_file}"
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} Failed to restore ${dtb2_file}!\n"
fi
fi
else
restoreerr=$((restoreerr+1))
echo -e "${Error}ERROR${Off} No backup to restore ${dtb2_file} from!\n"
fi
if [[ -z $restoreerr ]] || [[ $restoreerr -lt "1" ]]; then
echo -e "\nRestore successful."
rebootmsg
elif [[ $restoreerr == "1" ]]; then
echo -e "\nThere was $restoreerr restore error!"
else
echo -e "\nThere were $restoreerr restore errors!"
fi
else
echo -e "Nothing to restore."
fi
}
if [[ $restore == "yes" ]]; then
echo ""
restore_orig
echo ""
exit
fi
#----------------------------------------------------------
# Check currently enabled expansion units
supported_eunits=("DX517" "DX513" "DX213" "DX510" "RX418" "RX415" "RX410" \
"RX1217rp" "RX1217" "RX1214rp" "RX1214" "RX1211rp" "RX1211" \
"DX1215II" "DX1215" "DX1211")
check_modeldtb(){
# $1 is DX517 or RX418 etc
if [[ -f "${dtb2_file}" ]]; then
if grep -q "$1"'\b' "${dtb2_file}"; then
echo -e "${Cyan}$1${Off} is enabled in ${Yellow}${dtb2_file}${Off}" >& 2
else
echo -e "${Cyan}$1${Off} is ${Cyan}not${Off} enabled in ${Yellow}${dtb2_file}${Off}" >& 2
fi
fi
if [[ -f "${dtb_file}" ]]; then
if grep -q "$1"'\b' "${dtb_file}"; then
echo -e "${Cyan}$1${Off} is enabled in ${Yellow}${dtb_file}${Off}" >& 2
else
echo -e "${Cyan}$1${Off} is ${Cyan}not${Off} enabled in ${Yellow}${dtb_file}${Off}" >& 2
fi
fi
}
check_enabled(){
echo ""
for e in "${supported_eunits[@]}"; do
if grep -q "$e"'\b' "${dtb_file}"; then
check_modeldtb "${e#Synology-}"
fi
done
echo ""
}
if [[ $check == "yes" ]]; then
#echo ""
check_enabled
exit
fi
#------------------------------------------------------------------------------
# Enable unsupported Synology expansion units
backupdb(){
# Backup file if needed
if [[ -f "$1" ]]; then
if [[ ! -f "$1.bak" ]]; then
if [[ $(basename "$1") == "synoinfo.conf" ]]; then
echo "" >&2 # Formatting for stdout
fi
if [[ $2 == "long" ]]; then
fname="$1"
else
fname=$(basename -- "${1}")
fi
if cp -p "$1" "$1.bak"; then
echo -e "Backed up ${fname}" >&2
else
echo -e "${Error}ERROR 5${Off} Failed to backup ${fname}!" >&2
return 1
fi
fi
# Fix permissions if needed
octal=$(stat -c "%a %n" "$1" | cut -d" " -f1)
if [[ ! $octal -eq 644 ]]; then
chmod 644 "$1"
fi
else
echo -e "${Error}ERROR 5${Off} File not found: ${1}!" >&2
return 1
fi
return 0
}
dts_ebox(){
# $1 is the ebox model
# $2 is the dts file
# Remove last }; so we can append to dts file
sed -i '/^};/d' "$2"
# Append expansion unit node to dts file
if [[ $1 == DX517 ]] || [[ $1 == DX513 ]] || [[ $1 == DX510 ]]; then
cat >> "$2" <<EODX5bay
$1 {
compatible = "Synology";
model = "synology_${1,,}";
pmp_slot@1 {
libata {
EMID = <0x00>;
pmp_link = <0x00>;
};
};
pmp_slot@2 {
libata {
EMID = <0x00>;
pmp_link = <0x01>;
};
};
pmp_slot@3 {
libata {
EMID = <0x00>;
pmp_link = <0x02>;
};
};
pmp_slot@4 {
libata {
EMID = <0x00>;
pmp_link = <0x03>;
};
};
pmp_slot@5 {
libata {
EMID = <0x00>;
pmp_link = <0x04>;
};
};
};
};
EODX5bay
elif [[ $1 == DX213 ]]; then
cat >> "$2" <<EODX213
$1 {
compatible = "Synology";
model = "synology_${1,,}";
pmp_slot@1 {
libata {
EMID = <0x00>;
pmp_link = <0x00>;
};
};
pmp_slot@2 {
libata {
EMID = <0x00>;
pmp_link = <0x01>;
};
};
};
};
EODX213
elif [[ $1 == RX418 ]] || [[ $1 == RX415 ]] || [[ $1 == RX410 ]]; then
cat >> "$2" <<EORX4bay
$1 {
compatible = "Synology";
model = "synology_${1,,}";
pmp_slot@1 {
libata {
EMID = <0x00>;
pmp_link = <0x00>;
};
};
pmp_slot@2 {
libata {
EMID = <0x00>;
pmp_link = <0x01>;
};
};
pmp_slot@3 {
libata {
EMID = <0x00>;
pmp_link = <0x02>;
};
};
pmp_slot@4 {
libata {
EMID = <0x00>;
pmp_link = <0x03>;
};
};
};
};
EORX4bay
elif [[ ${_12bays[*]} =~ $1 ]]; then
cat >> "$2" <<EORX12bay
$1 {
compatible = "Synology";
model = "synology_rx1217rp";
pmp_slot@1 {
libata {
EMID = <0x00>;
pmp_link = <0x00>;
};
};
pmp_slot@2 {
libata {
EMID = <0x00>;
pmp_link = <0x01>;
};
};
pmp_slot@3 {
libata {
EMID = <0x00>;
pmp_link = <0x02>;
};
};
pmp_slot@4 {
libata {
EMID = <0x01>;
pmp_link = <0x00>;
};
};
pmp_slot@5 {
libata {
EMID = <0x01>;
pmp_link = <0x01>;
};
};
pmp_slot@6 {
libata {
EMID = <0x01>;
pmp_link = <0x02>;
};
};
pmp_slot@7 {
libata {
EMID = <0x02>;
pmp_link = <0x00>;
};
};
pmp_slot@8 {
libata {
EMID = <0x02>;
pmp_link = <0x01>;
};
};
pmp_slot@9 {
libata {
EMID = <0x02>;
pmp_link = <0x02>;
};
};
pmp_slot@10 {
libata {
EMID = <0x03>;
pmp_link = <0x00>;
};
};
pmp_slot@11 {
libata {
EMID = <0x03>;
pmp_link = <0x01>;
};
};
pmp_slot@12 {
libata {
EMID = <0x03>;
pmp_link = <0x02>;
};
};
};
};
EORX12bay
fi
}
install_binfile(){
# install_binfile <file> <file-url> <destination> <chmod> <bundled-path> <hash>
# example:
# file_url="https://raw.githubusercontent.com/${repo}/main/bin/dtc"
# install_binfile dtc "$file_url" /usr/bin/dtc a+x bin/dtc
if [[ -f "${scriptpath}/$5" ]]; then
binfile="${scriptpath}/$5"
echo -e "\nInstalling ${1}"
elif [[ -f "${scriptpath}/$(basename -- "$5")" ]]; then
binfile="${scriptpath}/$(basename -- "$5")"
echo -e "\nInstalling ${1}"
else
# Download binfile
if [[ $autoupdate == "yes" ]]; then
reply=y
else
echo -e "\nNeed to download ${1}"
echo -e "${Cyan}Do you want to download ${1}?${Off} [y/n]"
read -r -t 30 reply
fi
if [[ ${reply,,} == "y" ]]; then
echo -e "\nDownloading ${1}"
if ! curl -kL -m 30 --connect-timeout 5 "$2" -o "/tmp/$1"; then
echo -e "${Error}ERROR${Off} Failed to download ${1}!"
#return
exit 1 # Failed to download binfile
fi
binfile="/tmp/${1}"
printf "Downloaded md5: "
md5sum -b "$binfile" | awk '{print $1}'
md5=$(md5sum -b "$binfile" | awk '{print $1}')
if [[ $md5 != "$6" ]]; then
echo "Expected md5: $6"
echo -e "${Error}ERROR${Off} Downloaded $1 md5 hash does not match!"
exit 1 # Downloaded $1 md5 hash does not match
fi
else
echo -e "${Error}ERROR${Off} Cannot add expansion unit without ${1}!"
exit 1 # User answered no
fi
fi
# Set binfile executable
chmod "$4" "$binfile"
# Copy binfile to destination
cp -p "$binfile" "$3"
}
edit_modeldtb(){
# $1 is ebox model
if [[ -f /etc.defaults/model.dtb ]]; then # Is device tree model
# Check if dtc exists and is executable
if [[ ! -x $(which dtc) ]]; then
md5hash="01381dabbe86e13a2f4a8017b5552918"
branch="main"
file_url="https://raw.githubusercontent.com/${repo}/${branch}/bin/dtc"
# install_binfile <file> <file-url> <destination> <chmod> <bundled-path> <hash>
install_binfile dtc "$file_url" /usr/sbin/dtc "a+x" bin/dtc "$md5hash"
fi
# Check again if dtc exists and is executable
if [[ -x /usr/sbin/dtc ]]; then
# Backup model.dtb
backupdb "$dtb_file" || exit 1 # Failed to backup model.dtb
# Output model.dtb to model.dts
dtc -q -I dtb -O dts -o "$dts_file" "$dtb_file" # -q Suppress warnings
chmod 644 "$dts_file"
# Edit model.dts
for c in "${eboxes[@]}"; do
# Edit model.dts if needed
if ! grep -q "$c"'\b' "$dtb_file"; then
dts_ebox "$c" "$dts_file"
echo -e "Added ${Cyan}$c${Off} to ${Yellow}model${hwrev}.dtb${Off}" >&2
reboot=yes
else
echo -e "${Cyan}$c${Off} already enabled in ${Yellow}model${hwrev}.dtb${Off}" >&2
fi
done
# Compile model.dts to model.dtb
dtc -q -I dts -O dtb -o "$dtb_file" "$dts_file" # -q Suppress warnings
# Set owner and permissions for model.dtb
chmod a+r "$dtb_file"
chown root:root "$dtb_file"
cp -pu "$dtb_file" "$dtb2_file" # Copy dtb file to /etc
else
echo -e "${Error}ERROR${Off} Missing /usr/sbin/dtc or not executable!" >&2
exit
fi
fi
}
#------------------------------------------------------------------------------
# Select expansion unit to enable
# Show currently enabled eunit(s)
check_enabled
enable_eunit(){
case "$choice" in
DX517|DX513|DX510)
eboxes=("$choice") && edit_modeldtb
return
;;
DX213)
eboxes=("$choice") && edit_modeldtb
return
;;
RX418|RX415|RX410)
eboxes=("$choice") && edit_modeldtb
return
;;
RX1217rp|RX1214rp|RX1211rp)
eboxes=("$choice")
eboxes+=("${choice//rp}") # Also add non-RP model
edit_modeldtb
return
;;
RX1217|RX1214|RX1211)
eboxes=("$choice") && edit_modeldtb
return
;;
DX1215II|DX1215|DX1211)
eboxes=("$choice") && edit_modeldtb
return
;;
Check)
check_enabled
exit
;;
Restore)
restore_orig
return
;;
Quit) exit ;;
"") echo "Invalid Choice!" ;;
*)
echo -e "$choice not supported yet"
exit
;;
esac
}
_12bays=("RX1217rp" "RX1217" "RX1214rp" "RX1214" "RX1211rp" "RX1211" \
"DX1215II" "DX1215" "DX1211")
eunits=("DX517" "DX513" "DX213" "DX510" "RX418" "RX415" "RX410" \
"RX1217rp" "RX1217" "RX1214rp" "RX1214" "RX1211rp" "RX1211" \
"DX1215II" "DX1215" "DX1211" \
"Restore" "Quit")
if [[ -n $unit ]]; then
# Expansion Unit supplied as argument
if [[ ${eunits[*]} =~ ${unit} ]]; then
choice="${unit}"
echo -e "$choice selected\n"
enable_eunit
else
echo -e "Unsupported expansion unit argument: $unit\n"
exit 2 # Unsupported expansion unit argument
fi
else
PS3="Select your Expansion Unit: "
select choice in "${eunits[@]}"; do
echo -e "You selected $choice \n"
enable_eunit
break
done
fi
#echo ""
#------------------------------------------------------------------------------
# Finished
if [[ $reboot == "yes" ]]; then
rebootmsg
else
echo -e "\nFinished"
fi