Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ sudo amt-activate

That's it. Tool checks state, generates a strong password, activates, verifies. ~40-90 seconds total.

If your BIOS ships with manageability disabled (e.g. ThinkStation P3 Ultra 30HA), `amt-activate` detects the firmware refusal, offers to stage the BIOS toggle from Linux, and installs a self-disabling systemd unit that finishes activation at the next boot — your only action is the reboot. Non-interactive environments: `sudo amt-activate --auto-resume` does the same without prompting.

**Headless / automation note:** in sessions without a TTY (CI, agents, `ssh host cmd`), yay builds fine but its final `pacman -U` dies on the interactive sudo prompt. Build then install explicitly:

```bash
Expand Down Expand Up @@ -147,6 +149,8 @@ echo Enabled | sudo tee /sys/class/firmware-attributes/thinklmi/attributes/Manag

The change is staged in NVRAM and takes effect at the **next POST** — running `rpc activate` before rebooting fails with `AMT_STATUS_NOT_PERMITTED` / `Error 4: AmtNotReady`. Reboot once, then activate. Still no BIOS menu visit required.

`amt-activate` ≥ 0.2.0 automates this whole branch: on `AmtNotReady` it stages the toggle (tries `ManageabilityControl`, then `AMTControl`) and enables a one-shot `amt-autoactivate.service` that re-runs activation at boot with your saved password and disables itself on success.

#### Dell

| Line | Models | Local CCM | Notes |
Expand Down Expand Up @@ -268,7 +272,7 @@ sudo rpc deactivate -local
| Activation hangs 5-15 minutes | Expected on AMT 16.1.25 / AMT 18.x without LMS | Be patient. AMT 16.1.27 takes ~40s. AMT 18 may take 15 min per rpc-go #1119 |
| Activation never completes on AMT 19+ | LME interface removed in CSME 19.x | Install LMS daemon: `yay -S intel-amt-linux` ships LMS in Docker |
| `Execution timeout after 20s` × 3 then exit | AMT not in pre-provisioning, BIOS has AMT disabled, or OEM-preset MEBx password | Check `rpc amtinfo`; reset BIOS / Unconfigure AMT if MEBx is locked |
| `AMT_STATUS_NOT_PERMITTED` / `Error 4: AmtNotReady` on activate | Manageability disabled in BIOS — `rpc amtinfo` shows `Operational State: disabled`. ThinkStation P3 Ultra (30HA) ships this way from factory | Stage the BIOS toggle from Linux (Lenovo `think-lmi` / Dell `cctk`, see vendor table), reboot once, re-run `rpc activate -local -ccm` |
| `AMT_STATUS_NOT_PERMITTED` / `Error 4: AmtNotReady` on activate | Manageability disabled in BIOS — `rpc amtinfo` shows `Operational State: disabled`. ThinkStation P3 Ultra (30HA) ships this way from factory | `amt-activate` ≥ 0.2.0 offers to fix this automatically (stage toggle + resume unit + reboot). Manual: stage the BIOS toggle from Linux (Lenovo `think-lmi` / Dell `cctk`, see vendor table), reboot once, re-run `rpc activate -local -ccm` |
| IP stays `0.0.0.0` after activation | DHCP not yet leased | Wait 30-60s, re-run `rpc amtinfo`. AMT NIC requests DHCP after CCM transition completes |
| `401 Unauthorized` after activation | Known WiFi/802.1x sync bug on certain firmware | rpc-go #1310 — open issue as of May 2026 |
| `wsmancli`/`openwsman` build fails on Arch | Upstream openwsman is dead since 2019; Ruby rdoc build crash | Use `rpc-go-bin` instead; do not install wsmancli on Arch |
Expand Down
103 changes: 96 additions & 7 deletions scripts/amt-activate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,34 @@

set -euo pipefail

PW_FILE="${HOME}/.amt-mebx-password.txt"
PW_FILE="${AMT_PW_FILE:-${HOME}/.amt-mebx-password.txt}"
LOG_FILE="/tmp/amt-activate.log"
VERSION="0.1.1"
VERSION="0.2.0"

if [[ "${1:-}" == "--help" || "${1:-}" == "-h" ]]; then
cat <<EOF
amt-activate ${VERSION} — Activate Intel AMT in Client Control Mode from Linux

Usage: sudo amt-activate
Usage: sudo amt-activate [--auto-resume | --resume]

No flags. The script is interactive — it will:
Default (no flags) is interactive — it will:
1. Check /dev/mei0 and rpc binary
2. Run 'rpc amtinfo' to confirm pre-provisioning state
3. Generate or reuse password at ~/.amt-mebx-password.txt
4. Run 'rpc activate -local -ccm' and tee output to ${LOG_FILE}
5. Verify activation and report AMT IP

If the firmware refuses with AMT_STATUS_NOT_PERMITTED (manageability
disabled in BIOS), amt-activate offers to stage the BIOS toggle from
Linux and install a one-shot systemd unit so activation completes
automatically at the next boot — your only action is the reboot.

Flags:
--auto-resume Non-interactive: on NOT_PERMITTED, stage the BIOS
toggle and enable the resume unit without prompting
--resume Used by the systemd unit at boot: reuse the saved
password, activate, disable the unit on success

Docs: https://github.com/88plug/amt-activate-linux
Wiki: https://github.com/88plug/amt-activate-linux/wiki
Issues: https://github.com/88plug/amt-activate-linux/issues
Expand All @@ -41,11 +52,60 @@ if [[ "${1:-}" == "--version" || "${1:-}" == "-v" ]]; then
exit 0
fi

MODE="interactive"
case "${1:-}" in
--resume) MODE="resume" ;;
--auto-resume) MODE="auto" ;;
esac

RED=$'\e[31m' GRN=$'\e[32m' YLW=$'\e[33m' RST=$'\e[0m'
err() { echo "${RED}ERROR:${RST} $*" >&2; exit 1; }
info() { echo "${GRN}==>${RST} $*"; }
warn() { echo "${YLW}WARN:${RST} $*"; }

# Stage the BIOS manageability toggle from Linux (Lenovo think-lmi).
# Attribute name varies by platform: ManageabilityControl (P3 Ultra 30HA),
# AMTControl (T14 Gen 2+, X1 Gen 9+, M90q Gen 2+). Applies at next POST.
stage_bios_toggle() {
local base=/sys/class/firmware-attributes/thinklmi/attributes attr
for attr in ManageabilityControl AMTControl; do
if [ -e "$base/$attr/current_value" ]; then
info "Staging BIOS toggle: $attr=Enabled (applies at next POST)"
echo Enabled | sudo tee "$base/$attr/current_value" >/dev/null && return 0
fi
done
warn "No Lenovo think-lmi AMT attribute found."
echo " Dell: sudo cctk --AdvancedAmt=Enable"
echo " Other: enable AMT in BIOS setup once, then re-run amt-activate"
return 1
}

# Install a self-disabling one-shot unit so activation resumes at next boot.
install_resume_unit() {
local self; self=$(readlink -f "$0")
sudo tee /etc/systemd/system/amt-autoactivate.service >/dev/null <<UNIT
[Unit]
Description=Resume Intel AMT activation after BIOS manageability toggle applies
After=multi-user.target

[Service]
Type=oneshot
Environment=AMT_PW_FILE=${PW_FILE}
ExecStart=${self} --resume
TimeoutStartSec=300

[Install]
WantedBy=multi-user.target
UNIT
sudo systemctl daemon-reload
sudo systemctl enable amt-autoactivate.service
info "amt-autoactivate.service enabled — reboot to complete activation automatically."
}

disable_resume_unit() {
sudo systemctl disable amt-autoactivate.service 2>/dev/null || true
}

# ── prerequisites ──────────────────────────────────────────────────────────
[ -e /dev/mei0 ] || err "/dev/mei0 not found — run: sudo modprobe mei_me"
command -v rpc &>/dev/null || err "'rpc' not found — install rpc-go-bin: yay -S rpc-go-bin"
Expand All @@ -61,14 +121,25 @@ if echo "$AMT_INFO" | grep -qi "activated in client control mode"; then
info "AMT already activated in CCM. Nothing to do."
AMT_IP=$(echo "$AMT_INFO" | grep "AMT IP" | head -1 | awk '{print $NF}')
echo "AMT IP: ${AMT_IP:-check router DHCP table}"
[[ "$MODE" == "resume" ]] && disable_resume_unit
exit 0
fi

echo "$AMT_INFO" | grep -qi "pre-provisioning" || \
err "AMT not in pre-provisioning state (may already be configured differently)"

# ── password ───────────────────────────────────────────────────────────────
if [ -f "$PW_FILE" ]; then
if [[ "$MODE" != "interactive" ]]; then
# resume/auto: never prompt — reuse the saved password or create one
if [ -f "$PW_FILE" ]; then
PW=$(cat "$PW_FILE")
else
PW=$(openssl rand -base64 18 | tr -d '/+=' | head -c 14)
PW="${PW}A9!x"
echo "$PW" > "$PW_FILE"
chmod 0600 "$PW_FILE"
fi
elif [ -f "$PW_FILE" ]; then
warn "Password file already exists at $PW_FILE"
read -rp " Use existing password? [Y/n] " yn
if [[ "${yn:-y}" =~ ^[Nn] ]]; then
Expand Down Expand Up @@ -97,14 +168,32 @@ echo " Two 'Execution timeout after 20s' warnings are normal."
echo " Total time: ~40 seconds on CSME 16.x."
echo ""

sudo rpc activate -local -ccm -password "$PW" 2>&1 | tee "$LOG_FILE"
# rpc exits non-zero on refusal (e.g. Error 4 AmtNotReady) — '|| true' keeps
# set -euo pipefail from killing the script before the handlers below run.
sudo rpc activate -local -ccm -password "$PW" 2>&1 | tee "$LOG_FILE" || true
echo ""

if grep -q "Device activated in Client Control Mode" "$LOG_FILE"; then
info "Activation successful."
[[ "$MODE" == "resume" ]] && disable_resume_unit
elif grep -qE "AMT_STATUS_NOT_PERMITTED|AmtNotReady" "$LOG_FILE"; then
warn "Firmware refused activation: manageability is disabled in BIOS."
echo " Stage the toggle from Linux (no BIOS menu needed), reboot once, re-run:"
if [[ "$MODE" == "resume" ]]; then
# Toggle still not live (or staging never happened) — retry next boot.
warn "Leaving amt-autoactivate.service enabled for next boot."
exit 1
fi
if [[ "$MODE" == "auto" ]]; then
stage_bios_toggle && install_resume_unit && exit 0
exit 1
fi
if [ -t 0 ]; then
read -rp " Stage the BIOS toggle now and finish automatically after reboot? [Y/n] " yn
if [[ ! "${yn:-y}" =~ ^[Nn] ]]; then
stage_bios_toggle && install_resume_unit && exit 0
fi
fi
echo " Manual path — stage the toggle, reboot once, re-run amt-activate:"
echo " Lenovo: ls /sys/class/firmware-attributes/thinklmi/attributes/ | grep -iE 'amt|manage'"
echo " echo Enabled | sudo tee /sys/class/firmware-attributes/thinklmi/attributes/ManageabilityControl/current_value"
echo " Dell: sudo cctk --AdvancedAmt=Enable"
Expand Down