#!/bin/bash
# Derive stable per-unit MAC addresses for the two GMACs from the eMMC CID.
# This board carries no MAC anywhere: the i2c 24c02 ships blank and neither
# factory region holds one, so the kernel makes up a random MAC every boot.
set -u

cid_file="/sys/block/mmcblk0/device/cid"
[[ -r ${cid_file} ]] || exit 0
cid="$(< "${cid_file}")"
[[ -n ${cid} ]] || exit 0

hash="$(printf '%s' "${cid}" | sha256sum | cut -d' ' -f1)"

derive_mac() {
local off=$(( $1 * 12 )) first mac k
# clear the multicast bit and set the locally administered bit
printf -v first '%02x' $(( 0x${hash:${off}:2} & 0xfe | 0x02 ))
mac="${first}"
for k in 1 2 3 4 5; do
mac+=":${hash:$(( off + k * 2 )):2}"
done
printf '%s' "${mac}"
}

for ifpath in /sys/class/net/*; do
ifname="${ifpath##*/}"
of_name="$(udevadm info -q property -p "${ifpath}" 2>/dev/null | sed -n 's/^OF_FULLNAME=//p')"
case "${of_name}" in
*/ethernet@15100000/mac@0) index=0 ;;
*/ethernet@15100000/mac@1) index=1 ;;
*) continue ;;
esac

want="$(derive_mac "${index}")"
have="$(< "${ifpath}/address")"
[[ ${want} == "${have}" ]] && continue

# mtk_eth_soc refuses a MAC change while the interface is administratively up
was_up=""
[[ $(< "${ifpath}/flags") ]] && (( 0x$(sed 's/^0x//' "${ifpath}/flags") & 0x1 )) && was_up=yes
[[ -n ${was_up} ]] && ip link set dev "${ifname}" down

if ip link set dev "${ifname}" address "${want}" 2>/dev/null; then
echo "${ifname}: MAC set to ${want}"
else
echo "${ifname}: failed to set MAC ${want}" >&2
fi

[[ -n ${was_up} ]] && ip link set dev "${ifname}" up
done
