mirror of
https://github.com/RGBCube/nu_scripts
synced 2025-07-30 21:57:44 +00:00
Add nushell port of autoaspm (#1070)
This is a Nushell port of https://github.com/notthebee/AutoASPM written mostly as an exercise in binary operations in Nushell. There are several undocumented magic constants in the code that hail back from the original version that was supposed to be here: https://www.uwsg.indiana.edu/hypermail/linux/kernel/1006.2/02177.html
This commit is contained in:
parent
61bb4f6b50
commit
9ec9b2c7ab
2 changed files with 139 additions and 0 deletions
13
sourced/AutoASPM/README.md
Normal file
13
sourced/AutoASPM/README.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
## AutoASPM
|
||||
|
||||
Simple script to enable [Active State Power Management](https://en.wikipedia.org/wiki/Active_State_Power_Management) on all of your PCIe devices
|
||||
|
||||
This script supports only Linux systems
|
||||
|
||||
This is a Nushell port of [auto-ASPM.py](https://github.com/notthebee/AutoASPM) written mostly as an exercise in binary operations in Nushell.
|
||||
There are several undocumented magic constants in the code that hail back from the original [enable_aspm](https://www.uwsg.indiana.edu/hypermail/linux/kernel/1006.2/02177.html) script
|
||||
|
||||
### Usage
|
||||
|
||||
1. Ensure you have following binaries available on `PATH`: `lspci` `setpci`, those come as part of `pciutils` package on most distros
|
||||
2. Run the script as root (Necessary because regular users cannot access low-level device information needed for the script to work)
|
126
sourced/AutoASPM/auto_aspm.nu
Normal file
126
sourced/AutoASPM/auto_aspm.nu
Normal file
|
@ -0,0 +1,126 @@
|
|||
#!/usr/bin/env nu
|
||||
|
||||
const aspm = {
|
||||
DISABLED: 0b00
|
||||
L0s: 0b01
|
||||
L1: 0b10
|
||||
L0sL1: 0b11
|
||||
}
|
||||
|
||||
def get-bytes-for-device [
|
||||
device: string
|
||||
]: nothing -> binary {
|
||||
lspci -s $device -xxx
|
||||
| lines
|
||||
| skip
|
||||
| compact -e
|
||||
| split column -c ':'
|
||||
| get column2
|
||||
| split row ' '
|
||||
| compact -e
|
||||
| str join
|
||||
| decode hex
|
||||
| if ($in|bytes length) < 256 {
|
||||
print $"Invalid byte length detected for device ($device) aborting"
|
||||
exit
|
||||
} else {
|
||||
$in
|
||||
}
|
||||
}
|
||||
|
||||
def find-bytes [
|
||||
bytes: binary
|
||||
pos: int
|
||||
]: nothing -> int {
|
||||
# absolute black magic
|
||||
let result = ($bytes|bytes at $pos..$pos|into int)
|
||||
if $result != 0x10 {
|
||||
find-bytes $bytes ($result + 0x1)
|
||||
} else {
|
||||
return ($result + 0x10)
|
||||
}
|
||||
}
|
||||
|
||||
def patch-device [
|
||||
device: string
|
||||
aspm_value: string
|
||||
] {
|
||||
let bytes = (get-bytes-for-device $device)
|
||||
let byte_position = (find-bytes $bytes 0x34) #no one really knows where this value comes from
|
||||
let byte_to_patch = (
|
||||
$bytes
|
||||
| bytes at $byte_position..$byte_position
|
||||
| into int
|
||||
)
|
||||
# no idea
|
||||
if ($byte_to_patch| bits and 0b11) == ($aspm|get $aspm_value) {
|
||||
print $"($device) already has ASPM ($aspm_value) enabled"
|
||||
} else {
|
||||
print $"Enabling ASPM ($aspm_value) for device ($device)"
|
||||
let new_byte_value = (
|
||||
$byte_to_patch
|
||||
| bits shr 2 #no idea why we bitshift right and left
|
||||
| bits shl 2
|
||||
| bits or ($aspm|get $aspm_value)
|
||||
)
|
||||
patch-byte $device $byte_position $new_byte_value
|
||||
print $"Enabled ASPM ($aspm_value) for device ($device)"
|
||||
}
|
||||
}
|
||||
|
||||
def patch-byte [
|
||||
device: string
|
||||
position: int
|
||||
value: int
|
||||
] {
|
||||
setpci -s $device $"($position|format number|get upperhex).B=($value|format number|get upperhex)"
|
||||
}
|
||||
|
||||
def get-supported-devices []: nothing -> table<address: string, supported_aspm: string> {
|
||||
lspci -vv
|
||||
| lines
|
||||
| split list ''
|
||||
| each {|device|
|
||||
|
||||
let address = (
|
||||
$device
|
||||
| first
|
||||
| split row ' '
|
||||
| first
|
||||
)
|
||||
|
||||
let params = ($device|skip)
|
||||
|
||||
if ($params|find "ASPM"|is-empty) or ($params|find "ASPM not supported"|is-not-empty) {
|
||||
null
|
||||
} else {
|
||||
let supported_aspm = (
|
||||
$params
|
||||
| parse -r "ASPM (L[L0-1s ]*),"
|
||||
| get capture0.0
|
||||
| str replace " " ""
|
||||
)
|
||||
{address: $address, supported_aspm: $supported_aspm}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if not (is-admin) {
|
||||
error make -u {
|
||||
msg: "This script needs to be run as root"
|
||||
}
|
||||
}
|
||||
if $nu.os-info.name != "linux" {
|
||||
error make -u {
|
||||
msg: "This script needs to run under Linux"
|
||||
}
|
||||
}
|
||||
if (which lspci setpci|length) < 2 {
|
||||
error make -u {
|
||||
msg: "lspci and setpci need to be available in PATH"
|
||||
}
|
||||
}
|
||||
|
||||
for device in (get-supported-devices) {
|
||||
patch-device $device.address $device.supported_aspm
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue