CHECK_SIZE=false CHECK_MODEL=false CHECK_VENDOR=false CHECK_UUID=false CHECK_WWN=false CHECK_HCTL=false CHECK_SERIAL=false # URL/Percent decode a text function urldecode() { local encoded="${1//+/ }" printf '%b' "${encoded//%/\x}" } # Lowercase and url decode the values function normalize() { echo `urldecode "${1,,}"` } function _exec_lsblk() { lsblk -Pbio $2 /dev/$1 | head -n 1 | grep -Po "(?<=^$2=).*" | tr "\"" " " } # Get the block device size in GiB function get_size() { echo $(( (512 * $(cat /sys/block/$1/size) ) / 2**30)) } function get_model() { local file file=/sys/block/$1/device/model if [ -f $file ]; then normalize "$(cat $file)" fi } function get_vendor() { local file file=/sys/block/$1/device/vendor if [ -f $file ]; then normalize "$(cat $file)" fi } function get_wwn() { normalize "$(_exec_lsblk "$1" WWN)" } function get_serial() { normalize "$(_exec_lsblk "$1" SERIAL)" } # Parse all the hints from the Kernel cmdline and set the CHECK_* # variables function parse_hints() { IFS=',' read -ra H <<< "$ROOT_DEVICE" for i in "${H[@]}"; do case "$i" in size=*) CHECK_SIZE="${i#size=}" ;; model=*) CHECK_MODEL=`normalize "${i#model=}"` ;; vendor=*) CHECK_VENDOR=`normalize "${i#vendor=}"` ;; wwn=*) CHECK_WWN=`normalize "${i#wwn=}"` ;; serial=*) CHECK_SERIAL=`normalize "${i#serial=}"` ;; *) ;; esac done } function get_root_device() { # Parse the hints parse_hints for DEV in /sys/block/* ; do DEV_NAME=${DEV##*/} DEV_PATH=/dev/$DEV_NAME # Ignore loop and ram devices [[ $DEV_NAME = *loop* || $DEV_NAME = *ram* ]] && continue || : # Find out if it's a CDROM TYPE=/sys/block/$DEV_NAME/device/type [[ -f $TYPE ]] && (( $(cat "$TYPE") == 5 )) && continue || : [[ $CHECK_SIZE != false && $(get_size "$DEV_NAME") != $CHECK_SIZE ]] && continue || : [[ $CHECK_MODEL != false && $(get_model "$DEV_NAME") != $CHECK_MODEL ]] && continue || : [[ $CHECK_VENDOR != false && $(get_vendor "$DEV_NAME") != $CHECK_VENDOR ]] && continue || : [[ $CHECK_SERIAL != false && $(get_serial "$DEV_NAME") != $CHECK_SERIAL ]] && continue || : [[ $CHECK_WWN != false && $(get_wwn "$DEV_NAME") != $CHECK_WWN ]] && continue || : # A device that matches all hints was found echo "$DEV_PATH" break done }