Skip to content

Instantly share code, notes, and snippets.

@Low-power
Last active Oct 14, 2021
Embed
What would you like to do?
Command line wrapper for Solaris pm(7D).
#!/usr/bin/sh
# Copyright 2015-2021 Rivoreo
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# From sys/pm.h
PM_SET_DEVICE_THRESHOLD=18
PM_GET_SYSTEM_THRESHOLD=19
PM_SET_SYSTEM_THRESHOLD=20
PM_START_PM=21
PM_STOP_PM=22
PM_RESET_PM=23
PM_GET_STATS=24
PM_GET_DEVICE_THRESHOLD=25
PM_GET_POWER_NAME=26
PM_GET_POWER_LEVELS=27
PM_GET_NUM_COMPONENTS=28
PM_GET_COMPONENT_NAME=29
PM_GET_NUM_POWER_LEVELS=30
PM_GET_STATE_CHANGE=31
PM_GET_STATE_CHANGE_WAIT=32
PM_DIRECT_PM=33
PM_RELEASE_DIRECT_PM=34
PM_DIRECT_NOTIFY=35
PM_DIRECT_NOTIFY_WAIT=36
PM_RESET_DEVICE_THRESHOLD=37
PM_GET_PM_STATE=38
PM_GET_DEVICE_TYPE=39
PM_SET_COMPONENT_THRESHOLDS=40
PM_GET_COMPONENT_THRESHOLDS=41
PM_IDLE_DOWN=42
PM_GET_DEVICE_THRESHOLD_BASIS=43
PM_SET_CURRENT_POWER=44
PM_GET_CURRENT_POWER=45
PM_GET_FULL_POWER=46
PM_ADD_DEPENDENT=47
PM_GET_TIME_IDLE=48
PM_GET_DEFAULT_SYSTEM_THRESHOLD=49
PM_ADD_DEPENDENT_PROPERTY=50
PM_START_CPUPM=51
PM_START_CPUPM_EV=52
PM_START_CPUPM_POLL=53
PM_STOP_CPUPM=54
PM_GET_CPU_THRESHOLD=55
PM_SET_CPU_THRESHOLD=56
PM_GET_CPUPM_STATE=57
PM_ENABLE_S3=58
PM_DISABLE_S3=59
PM_ENTER_S3=60
PM_START_AUTOS3=61
PM_STOP_AUTOS3=62
PM_SEARCH_LIST=63
PM_GET_AUTOS3_STATE=64
PM_GET_S3_SUPPORT_STATE=65
PM_GET_CMD_NAME=66
PM_DISABLE_CPU_DEEP_IDLE=67
PM_ENABLE_CPU_DEEP_IDLE=68
PM_DEFAULT_CPU_DEEP_IDLE=69
# struct pm_req {
# char *physpath; /* physical path of device to configure */
# /* see libdevinfo(3) */
# int component; /* Selects the component of the device */
# int value; /* power level, threshold value, or count */
# void *data; /* command-dependent variable sized data */
# size_t datasize; /* Size of data buffer */
# };
# Return values from ioctl commands that return pm state info.
PM_SYSTEM_PM_ENABLED=0
PM_SYSTEM_PM_DISABLED=1
PM_NO_PM_COMPONENTS=2
PM_CREATE_COMPONENTS=3
PM_AUTOPM=4
PM_DEFAULT_THRESHOLD=5
PM_DEVICE_THRESHOLD=6
PM_COMPONENT_THRESHOLD=7
PM_OLD_THRESHOLD=8
PM_DIRECTLY_MANAGED=9
PM_CPU_THRESHOLD=10
PM_CPU_PM_ENABLED=11
PM_CPU_PM_DISABLED=12
PM_CPU_PM_NOTSET=13
PM_AUTOS3_ENABLED=14
PM_AUTOS3_DISABLED=15
PM_S3_SUPPORT_ENABLED=16
PM_S3_SUPPORT_DISABLED=17
print_usage() {
printf "Usage: %s <subcommand> [<options>]\\n" "$1" 1>&2
cat 1>&2 << EOT
Available subcommands:
getsystemthreshold
pmstate
startcpupm [--event|--poll]
stopcpupm
cpupmstate
getcputhreshold
setcputhreshold <value>|always-on
EOT
}
set -e
argv0="${0##*/}"
case "$1" in
getsystemthreshold)
toolbox ioctl /dev/pm $PM_GET_SYSTEM_THRESHOLD
;;
pmstate)
v="`toolbox ioctl /dev/pm $PM_GET_PM_STATE`"
case "$v" in
$PM_SYSTEM_PM_ENABLED)
echo Enabled
exit 0
;;
$PM_SYSTEM_PM_DISABLED)
echo Disabled
exit 1
;;
*)
printf "Unknown return value '%s'\\n" "$v" 1>&2
exit 3
;;
esac
;;
startcpupm)
if [ $# -gt 2 ]; then
printf "Usage: %s startcpupm [--event|--poll]\\n" "$argv0" 1>&2
exit 255
fi
if [ $# = 2 ]; then case "$2" in
--event)
req=$PM_START_CPUPM_EV
;;
--poll)
req=$PM_START_CPUPM_POLL
;;
-*)
printf "Invalid option '%s'\\n" "$2" 1>&2
exit 255
;;
*)
printf "Usage: %s startcpupm [--event|--poll]\\n" "$argv0" 1>&2
exit 255
;;
esac elif [ "`toolbox ioctl /dev/pm $PM_GET_CPUPM_STATE`" = $PM_CPU_PM_ENABLED ]; then
echo "CPU power management is already enabled" 1>&2
exit 0
else
req=$PM_START_CPUPM_POLL
fi
v="`toolbox ioctl /dev/pm $req`"
[ "$v" != 0 ] && printf "Return value %s\\n" "$v"
;;
stopcpupm)
v="`toolbox ioctl /dev/pm $PM_STOP_CPUPM`"
[ "$v" != 0 ] && printf "Return value %s\\n" "$v"
;;
cpupmstate)
v="`toolbox ioctl /dev/pm $PM_GET_CPUPM_STATE`"
case "$v" in
$PM_CPU_PM_ENABLED)
echo Enabled
exit 0
;;
$PM_CPU_PM_DISABLED)
echo Disabled
exit 1
;;
$PM_CPU_PM_NOTSET)
echo "Not set"
exit 2
;;
*)
printf "Unknown return value '%s'\\n" "$v" 1>&2
exit 3
;;
esac
;;
getcputhreshold)
toolbox ioctl /dev/pm $PM_GET_CPU_THRESHOLD
;;
setcputhreshold)
if [ $# != 2 ]; then
printf "Usage: %s setcputhreshold <value>|always-on\\n" "$argv0" 1>&2
exit 255
fi
v="$2"
case "$v" in
always-on)
v=0x7fffffff
;;
*h)
v=$((${v%h}*3600))
;;
*m)
v=$((${v%m}*60))
;;
0x[0-9a-fA-F]|0x[0-9a-fA-F]*[0-9a-fA-F])
;;
[0-9]|[0-9]*[0-9])
;;
*)
printf "Invalid value '%s'\\n" "$v" 1>&2
exit 255
;;
esac
if [ $((v)) -lt 0 ] || [ $((v)) -gt $((0x7fffffff)) ]; then
printf "Value '%s' is out of range\\n" "$v" 1>&2
exit 255
fi
v="`toolbox ioctl -d /dev/pm $PM_SET_CPU_THRESHOLD \"$v\"`"
v="${v%%
*}"
[ "$v" != 0 ] && printf "Return value %s\\n" "$v"
;;
--help)
print_usage "$argv0"
exit 0
;;
*)
print_usage "$argv0"
exit 255
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment