-
Notifications
You must be signed in to change notification settings - Fork 0
/
sedutil-helper
executable file
·120 lines (109 loc) · 3.67 KB
/
sedutil-helper
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/bin/sh
# sedutil-helper (part of ossobv/sedutil-deb) // wdoekes/2022,2024
# // Public Domain
#
# Script to simplify unlocking multiple drives with the same password.
#
set -eu
PASSWORD=${SED_PASSWORD:-}
DEVICES=${SED_DEVICES:-}
ARGV0=${0##*/}
case ${1:-} in
-h|--help)
echo 'Helper for Self-encrypting drives (SED)'
echo 'usage: sedutil-helper # to list SED drives'
echo 'usage: sedutil-unlock # to unlock SED drives'
echo
echo 'optional env: SED_DEVICES SED_PASSWORD'
exit 0
esac
if test $# -ne 0; then
echo "unexpected args, see --help" >&2
exit 1
fi
if ! command -v sedutil-cli >/dev/null; then
echo "you have no sedutil-cli" >&2
exit 1
fi
try_lock() {
local dev="$1"
local pci=
for pci in /dev/disk/by-path/pci*; do
test "$(readlink -f "$pci")" = "$dev" && break
pci=
done
if test -n "$pci"; then
# /dev/disk/by-path/pci-0000:c3:00.0-nvme-1
local address
address=${pci##*/pci-}
address=${address%.*}
local slot
slot=$(grep -lxF "$address" /sys/bus/pci/slots/*/address)
if test -n "$slot"; then
# THIS HAS UNEXPECTED EFFECTS; NOT SURE IF YOU WANT THIS
echo "> $pci -> $(readlink -f "$pci")"
echo "> cat $slot # $(cat $slot)"
echo '# zpool export POOL # do this first'
echo "# echo 0 >${slot%/address}/power # then this at own risk!"
echo "# echo 1 >${slot%/address}/power # after some waiting"
fi
fi
echo '(the above is not implemented; type stuff at your own risk)' >&2
}
try_unlock() {
local dev="$1"
if test -z "$PASSWORD"; then
if test -t 0; then
echo -n " supply password to unlock: "
read PASSWORD
fi
fi
if test -n "$PASSWORD"; then
if sedutil-cli --setLockingRange 0 RW "$PASSWORD" "$dev"; then
local try
# I think this works immediately. But we may need to see
# some live action in the field to confirm.
for try in 1 1 1 1 1 1 1 0; do
partx -u "$dev" 2>/dev/null && break || true
echo -n .
sleep $try
done
if test $try -eq 0; then
partx -u "$dev" || echo "failed to load partitions on $dev"
fi
fi
fi
}
if test -z "$DEVICES"; then
DEVICES=$(nvme list | awk '/^\/dev\//{print $1}' | LC_ALL=C sort -Vu)
fi
for dev in $DEVICES; do
if ! sedutil-cli --isValidSED "$dev" 2>/dev/null |
grep -q '[[:blank:]]SED[[:blank:]]'; then
echo "$dev is NOT A SED DEVICE" >&2
continue
fi
query=$(sedutil-cli --query "$dev" | cat -v)
locked_value=$(printf '%s' "$query" | sed -ne '
s/.*[[:blank:]]Locked[[:blank:]]*=[[:blank:]]*\(.\).*/\1/p')
locking_enabled_value=$(printf '%s' "$query" | sed -ne '
s/.*[[:blank:]]LockingEnabled[[:blank:]]*=[[:blank:]]*\(.\).*/\1/p')
locking_supported_value=$(printf '%s' "$query" | sed -ne '
s/.*[[:blank:]]LockingSupported[[:blank:]]*=[[:blank:]]*\(.\).*/\1/p')
can_has_is="$locking_supported_value$locking_enabled_value$locked_value"
if test "$can_has_is" = "YYY"; then # {can,has,is} lock(ed)
echo "$dev is locked"
if test "$ARGV0" = sedutil-unlock; then
try_unlock "$dev"
fi
elif test "$can_has_is" = "YYN"; then # {can,has,is} lock(ed)
echo "$dev is NOT locked"
if test "$ARGV0" = sedutil-lock; then
try_lock "$dev"
fi
else
echo "$dev has unexpected lock state:\
supported=$locking_supported_value enabled=$locking_enabled_value\
is_locked=$locked_value"
fi
done