1#!/bin/bash -eu 2 3# SPDX-License-Identifier: Apache-2.0 4# Copyright 2020-2021 YADRO 5 6log_msg() { 7 echo "$@" 8} 9 10log_err() { 11 echo "$@" >&2 12} 13 14read_hw_mac() { 15 local iface="$1" 16 cat /sys/class/net/"${iface}"/address 2>/dev/null ||: 17} 18 19set_hw_mac() { 20 local iface="$1" 21 local mac="$2" 22 local up="" 23 if ip link show dev "${iface}" | grep -q "${iface}:.*\<UP\>" 2>/dev/null; then 24 up=true 25 fi 26 27 if [ "${up}" = true ]; then 28 ip link set dev "${iface}" down ||: 29 fi 30 ip link set dev "${iface}" address "${mac}" ||: 31 if [ "${up}" = true ]; then 32 ip link set dev "${iface}" up ||: 33 fi 34} 35 36set_fw_env_mac() { 37 local iface="$1" 38 local mac="$2" 39 local envname="" 40 case "${iface}" in 41 eth0) 42 envname="ethaddr" 43 ;; 44 eth1) 45 envname="eth1addr" 46 ;; 47 *) 48 return 1 49 ;; 50 esac 51 if ! fw_setenv "$envname" "$mac"; then 52 return 1 53 fi 54} 55 56######## MAIN ######## 57FRU_DBUS_SERVICE="xyz.openbmc_project.FruDevice" 58FRU_DBUS_OBJECT_TEMPLATE="\/xyz.*_Motherboard" 59FRU_DBUS_INTERFACE="xyz.openbmc_project.FruDevice" 60fru_dbus_object="" 61 62######## Parse D-bus data ######## 63n=1 64while true; do 65 fru_dbus_object=$(busctl tree ${FRU_DBUS_SERVICE} 2>/dev/null | 66 sed -n "s/^.*\(${FRU_DBUS_OBJECT_TEMPLATE}\).*$/\1/p" 67 ) && [ -n "${fru_dbus_object}" ] && break 68 if [ ${n} -lt 15 ]; then 69 n=$((n+1)) 70 sleep 1 71 else 72 log_err "Failed to find baseboard FRU object" 73 exit 1 74 fi 75done 76 77dbusData=$(dbus-send --system --print-reply=literal \ 78 --dest=${FRU_DBUS_SERVICE} \ 79 "${fru_dbus_object}" \ 80 org.freedesktop.DBus.Properties.GetAll \ 81 string:${FRU_DBUS_INTERFACE} 2>/dev/null ||:) 82 83if [ -z "${dbusData}" ]; then 84 log_err "Failed to get data from D-Bus" 85 exit 1 86fi 87 88# This awk script matches strings 010xyyyyyyyyyyyy, where x is interface index 89# and yyyyyyyyyyyy - interface mac address. 90# The output would be in form ethx=yy:yy:yy:yy:yy:yy 91macsList=$(echo "${dbusData}" | \ 92 awk '/BOARD_INFO_AM[0-9]+\s+variant\s+010[0-9a-f]{13}/{ 93 totalMacDigits=12 94 singleOctet=2 95 offset=4 96 printf "eth%s=", substr($3, offset, 1) 97 for(i = 1 + offset; i < totalMacDigits + offset; i += singleOctet) { 98 printf "%s", substr($3, i, singleOctet) 99 if (i <= totalMacDigits + offset - singleOctet) printf ":" 100 } 101 printf "\n" 102 }'||:) 103 104if [ -z "${macsList}" ]; then 105 log_err "Failed to get MAC address" 106 exit 1 107fi 108 109# Get hardware model name from PRODUCT_PRODUCT_NAME 110# Examples: 111# 'VEGMAN N110 Server' -> 'VEGMAN-N110' 112# 'TATLIN.ARCHIVE.XS' -> 'TATLIN-ARCHIVE-XS' 113modelName=$(echo "${dbusData}" | \ 114 awk '/PRODUCT_PRODUCT_NAME\s+variant\s+/{ 115 if ($3 ~ /^VEGMAN/) { 116 printf "%s-%s", $3, $4 117 } else if ($3 ~ /^TATLIN/) { 118 print gensub(/\./, "-", "g", $3) 119 } 120 }'||:) 121 122serialNumber=$(echo "${dbusData}" | \ 123 awk '/PRODUCT_SERIAL_NUMBER\s+variant\s+/{print $3}'||:) 124if [ -z "${serialNumber}" ]; then 125 log_err "Failed to get product Serial Number" 126 exit 1 127fi 128 129# shellcheck disable=SC1091 130source /etc/os-release 131 132 133######## Check and set MAC addresses ######## 134retCode=0 135IFS=' 136' 137for line in ${macsList} ; do 138 ifaceName=$(echo "${line}" | cut -f 1 -d '=' || :) 139 macAddr=$(echo "${line}" | cut -f 2- -d '=' || :) 140 if [ -n "${ifaceName}" ] && [ -n "${macAddr}" ]; then 141 curMacAddr=$(read_hw_mac "${ifaceName}") 142 if [ "${macAddr}" != "${curMacAddr}" ] ; then 143 log_msg "Changing MAC address for ${ifaceName}: ${curMacAddr} -> ${macAddr}" 144 # A factory assigned address was found, and it is newly assigned. 145 # Update the active interface and save the new value to the u-boot 146 # environment. 147 if ! set_hw_mac "${ifaceName}" "${macAddr}"; then 148 log_err "Failed to set address" 149 retCode=1 150 fi 151 if ! set_fw_env_mac "${ifaceName}" "${macAddr}"; then 152 log_err "Failed to set boot env for ${ifaceName}" 153 retCode=1 154 fi 155 fi 156 fi 157 158 [ ${retCode} -eq 0 ] || exit ${retCode} 159done 160 161 162######## Check and set hostname ######## 163hostname=$(hostname) 164if [ "${OPENBMC_TARGET_MACHINE}" = "${hostname}" ] ; then 165 hostname="${modelName,,}-${serialNumber}" 166 log_msg "Changing hostname to ${hostname}" 167 168 if ! hostnamectl set-hostname "${hostname}"; then 169 log_err "Failed to set new hostname" 170 exit 1 171 fi 172fi 173 174######## Run optional scripts ######## 175snmp_handler="/usr/sbin/snmpd-generate-conf.sh" 176if [ -x ${snmp_handler} ]; then 177 if ! ${snmp_handler} "${modelName}"; then 178 log_err "Failed to setup snmp" 179 fi 180fi 181