#!/bin/sh
#
# unos-firstboot -- one-time platform provisioning
#
# A UNOS image is identical on every machine. Hardware support is added
# afterwards, by package. This runs once on first boot, works out what the
# machine actually is, and pulls in whatever it needs.
#
# Invoked from runit stage 1. Safe to re-run: it is a no-op once the marker
# exists, and `--force` re-runs the detection.

set -e

STATEDIR=/var/lib/unos
MARKER="${STATEDIR}/.provisioned"
FORCE=0

log() { echo "unos-firstboot: $*"; }

while [ $# -gt 0 ]; do
  case "$1" in
    --force) FORCE=1 ;;
    *) log "unknown argument: $1"; exit 1 ;;
  esac
  shift
done

if [ -e "${MARKER}" ] && [ "${FORCE}" -eq 0 ]; then
  exit 0
fi

# Broadcom XGS switch ASICs sit on PCIe under vendor 0x14e4 with device IDs in
# the 0xb??? range (BCM56xxx / BCM78xxx). Broadcom NICs share the vendor ID but
# use different device ranges, so the device prefix is what distinguishes them.
#
# Read straight out of sysfs rather than shelling out to lspci, which busybox
# does not provide.
#
# NOTE: verify the device ID range against real hardware before trusting this
# on a platform we have not seen.
detect_bcm_switch() {
  for dev in /sys/bus/pci/devices/*; do
    [ -r "${dev}/vendor" ] || continue
    [ -r "${dev}/device" ] || continue

    read -r vendor < "${dev}/vendor"
    [ "${vendor}" = "0x14e4" ] || continue

    read -r device < "${dev}/device"
    case "${device}" in
      0xb*)
        log "found Broadcom switch ASIC at $(basename "${dev}") (${vendor}:${device})"
        return 0
        ;;
    esac
  done
  return 1
}

install_pkg() {
  log "installing $1"
  if ! apk add "$1"; then
    log "failed to install $1"
    return 1
  fi
}

mkdir -p "${STATEDIR}"

if detect_bcm_switch; then
  log "platform: broadcom xgs switch"
  install_pkg openbcm || exit 1
else
  log "platform: generic, no switching ASIC detected"
  log "linkd will use the built-in kernel dataplane"
fi

date -u +%Y-%m-%dT%H:%M:%SZ > "${MARKER}"
log "provisioning complete"
