-
-
Save briantully/65b4b878d1b7f4c1e4444b255c714d69 to your computer and use it in GitHub Desktop.
macOS nvram boot variables, device properties, EFI device paths
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# joevt Dec 30, 2020 | |
# https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123 | |
gfxutilcmd=~/Downloads/gfxutil | |
alias gfxutil="'$gfxutilcmd'" | |
nvramp () { | |
local thename="$1" | |
local thedata="" # must declare local separately for $? to get the error | |
thedata="$(nvram $thename)" | |
local theerr=$? | |
printf "$(sed -E '/^'$thename'./s///;s/\\/\\\\/g;s/%/\\x/g' <<< "$thedata")" | |
return $theerr | |
} | |
efiguid=8BE4DF61-93CA-11D2-AA0D-00E098032B8C | |
bootvar () { | |
local thebootvar=$1 | |
local thebytes="$(nvramp $efiguid:"$thebootvar" | xxd -p -c 99999; echo ${pipestatus[1]}${PIPESTATUS[0]})" | |
# typedef struct _EFI_LOAD_OPTION | |
local theerr=$(sed -n \$p <<< "$thebytes") | |
if (( !$theerr )); then | |
thebytes=$(sed \$d <<< "$thebytes") | |
local theAttributes=$((0x${thebytes:6:2}${thebytes:4:2}${thebytes:2:2}${thebytes:0:2})) | |
# 0x00000001 LOAD_OPTION_ACTIVE | |
# 0x00000002 LOAD_OPTION_FORCE_RECONNECT | |
# 0x00000008 LOAD_OPTION_HIDDEN | |
# 0x00001F00 LOAD_OPTION_CATEGORY | |
# 0x00000000 LOAD_OPTION_CATEGORY_BOOT | |
# 0x00000100 LOAD_OPTION_CATEGORY_APP | |
local theFilePathListLength=$((0x${thebytes:10:2}${thebytes:8:2})) | |
local theDescription=$(xxd -p -r <<< "${thebytes:12}" | iconv -f UTF-16LE -t UTF-8 | tr '\0' '\n' | sed -n -E '1p' | tr -d '\n') | |
local theoffset=$(( 6 + (${#theDescription}+1) * 2 )) | |
local theFilePathList=${thebytes:$theoffset * 2:$theFilePathListLength*2} | |
((theoffset += theFilePathListLength)) | |
local theOptionalData=${thebytes:$theoffset * 2} | |
local theOptionalDatastring=$(xxd -p -r <<< "${theOptionalData}" | iconv -f UTF-16LE -t UTF-8 | tr '\0' '\n' | sed -n -E '1p' | tr -d '\n') | |
echo -n "$thebootvar: $theAttributes, "'"'"$theDescription"'"' | |
[[ -n $theFilePathList ]] && { | |
echo -n ', "'; gfxutil "$theFilePathList" | cat; echo -n '"' | |
} | |
[[ -n $theOptionalData ]] && echo -n ", "'"'"$theOptionalDatastring"'"' | |
echo | |
[[ -n $theOptionalData ]] && { | |
echo $theOptionalData | xxd -p -r | xxd -o $theoffset -g $((${#theOptionalData}/2)) -c $((${#theOptionalData}/2)) | perl -pe "s/^([0-9A-Fa-f]+: )([0-9A-Fa-f]+) (.*)/ \1\2\n \1\3/" | |
} | |
fi | |
return $theerr | |
} | |
setbootvar () { | |
local thebootvar=$1 | |
local theAttributes=$2 | |
local theDescription=$3 | |
local theFilePathList=$4 | |
local theOptionalData=$5 | |
local theAttributesBytes=$(printf "%08x" "$theAttributes") | |
local theFilePathListBytes=$(gfxutil "$theFilePathList") | |
local theDescriptionBytes=$(printf "${theDescription}\0" | iconv -f UTF-8 -t UTF-16LE | xxd -p -c 999999) | |
local theFilePathListLength=$((${#theFilePathListBytes} / 2)) | |
local theFilePathListLengthBytes=$(printf "%04x" $theFilePathListLength) | |
local thebytes="${theAttributesBytes:6:2}${theAttributesBytes:4:2}${theAttributesBytes:2:2}${theAttributesBytes:0:2}"\ | |
"${theFilePathListLengthBytes:2:2}${theFilePathListLengthBytes:0:2}"\ | |
"${theDescriptionBytes}"\ | |
"${theFilePathListBytes}"\ | |
"${theOptionalData}" | |
sudo nvram "${efiguid}:${thebootvar}=$(sed -E 's/(..)/%\1/g' <<< ${thebytes})" | |
} | |
setbootorder () { | |
IFS='' | |
local thestring="$*" | |
sudo nvram "${efiguid}:BootOrder=$(sed -E "s/[Bb]oot//g;s/(..)(..)/%\2%\1/g" <<< $thestring)" | |
} | |
setdriverorder () { | |
IFS='' | |
local thestring="$*" | |
sudo nvram "${efiguid}:DriverOrder=$(sed -E "s/[Dd]river//g;s/(..)(..)/%\2%\1/g" <<< $thestring)" | |
} | |
dumpallbootvars () { | |
for theboot in Current Next; do | |
local BootWhat=$(nvramp $efiguid:Boot$theboot 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'Boot'\2\1 /g') | |
echo "Boot$theboot: $BootWhat" | |
done | |
echo | |
for theType in Boot Driver; do | |
local BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'${theType}'\2\1 /g') | |
echo "${theType}Order: $BootOrder" | |
IFS=$' ' | |
for theboot in $(echo $BootOrder); do | |
bootvar $theboot 2> /dev/null | |
done | |
#echo "Search loop" | |
IFS=$'\n' | |
local lowboot=-1 | |
for boot in $( { | |
eval $(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/echo $((0x\2\1 + 1)):1;echo $((0x\2\1 - 1)):-1;/g'); echo 0:1; echo 127:-1; echo 128:1; echo $((0xFFFF)):-1 | |
} | sort -u -t : -k 1n,2n | |
) ; do | |
#echo "checking range $boot" | |
local inc="${boot#*:}" | |
local boot=$((${boot%:*})) | |
local first=1 | |
while ((1)); do | |
#echo " checking boot:$boot inc:$inc lowboot:$lowboot" | |
thebootvar=${theType}$(printf "%04X" $boot) | |
[[ $BootOrder != *"$thebootvar"* ]] || break | |
((boot > lowboot)) || break | |
((inc > 0)) && ((lowboot = boot)) | |
if ((first)); then | |
echo "Searching: $thebootvar" | |
first=0 | |
fi | |
bootvar $thebootvar 2> /dev/null || break | |
((boot+=inc)) | |
done | |
((inc < 0)) && ((lowboot = boot)) | |
done | |
echo | |
done | |
} | |
dumpallioregefipaths () { | |
eval "$( | |
(ioreg -lw0 -p IODeviceTree; ioreg -lw0) | perl -e ' | |
$thepath=""; while (<>) { | |
if ( /^([ |]*)\+\-o (.+) </ ) { $indent = (length $1) / 2; $name = $2; $thepath =~ s|^((/[^/]*){$indent}).*|$1/$name| } | |
if ( /^[ |]*"([^"]+)" = <(.*7fff0400.*)>/i ) { print $thepath . "/" . $1 . " = <" . $2 . ">\n" } | |
} | |
' | sed -E '/device-properties/d;/(.*) = <(.*)>/s//echo -n "\1 = "; gfxutil \2 | cat; echo/' | |
)" | |
} | |
ioregp () { | |
ioreg -n "$2" -w0 -p "$1" -k "$3" | sed -nE 's/^[ |]+"'"$3"'" = <(.*)>/\1/p' | xxd -p -r | |
} | |
getdeviceprops () { | |
ioreg -rw0 -p IODeviceTree -n efi | grep device-properties | sed 's/.*<//;s/>.*//;' | xxd -p -r | |
} | |
getaaplpathprops () { | |
# Get device properties from nvram AAPL,PathProperties0000,0001,etc. | |
# (max 768 per nvram var) | |
i=0 | |
while (( 1 )); do | |
thevar="4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:AAPL,PathProperties$(printf "%04X" $i)" | |
theval="$(nvram "$thevar" 2> /dev/null)" | |
[[ -z $theval ]] && break | |
printf "$(echo -n "$theval" | sed -E '/^'$thevar'./s///;s/\\/\\\\/g;s/%/\\x/g')" | |
((i++)) | |
done | |
} | |
setaaplpathprops () { | |
local thefile="$1" | |
local theproperties=$(xxd -p -c 99999 "$1") | |
local thevar=0 | |
while ((1)); do | |
local thepart=${theproperties:$thevar*768*2:768*2} | |
local thename="4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:AAPL,PathProperties"$(printf "%04X" thevar) | |
if [[ -n $thepart ]]; then | |
sudo nvram "${thename}=$(sed -E 's/(..)/%\1/g' <<< ${thepart})" | |
else | |
nvram "${thename}" > /dev/null 2>&1 && sudo nvram -d "$thename" || break | |
fi | |
((thevar++)) | |
done | |
} | |
getpanic () { | |
# Get device properties from nvram AAPL,PanicInfo000K,000M,etc. | |
# (max 768 per nvram var) | |
i=0 | |
while (( 1 )); do | |
thevar="AAPL,PanicInfo000$(printf "%02x" $((0x$(printf 'K' | xxd -p) + i)) | xxd -p -r)" | |
theval="$(nvram "$thevar" 2> /dev/null)" | |
[[ -z $theval ]] && break | |
printf "$(echo -n "$theval" | sed -E '/^'$thevar'./s///;s/\\/\\\\/g;s/%/\\x/g')" | |
((i++)) | |
done | |
} | |
getpanic2 () { | |
# Get device properties from nvram aapl,panic-info | |
# (max 768 per nvram var) | |
i=0 | |
while (( 1 )); do | |
thevar="aapl,panic-info" | |
theval="$(nvram "$thevar" 2> /dev/null)" | |
[[ -z $theval ]] && break | |
printf "$(echo -n "$theval" | sed -E '/^'$thevar'./s///;s/\\/\\\\/g;s/%/\\x/g')" | |
((i++)) | |
break | |
done | |
} | |
testbit () { | |
local isset=$1 | |
local fbits=$(($2)) | |
local fmask=$(($3)) | |
local fbit=$(($4)) | |
local fname=$5 | |
if [[ $isset = "printset" ]]; then | |
if ((fbit & fbits)); then | |
printf $fname | |
if ((!(fbit & fmask))); then | |
printf "(error: mask is 0)" | |
fi | |
printf "\n" | |
fi | |
elif [[ $isset = "printunset" ]]; then | |
if ((!(fbit & fbits))); then | |
if (((fbit & fmask))); then | |
printf "not $fname" | |
printf "\n" | |
fi | |
fi | |
elif [[ $isset = "printignored" ]]; then | |
if ((!(fbit & fmask))); then | |
printf "ignore $fname" | |
printf "\n" | |
fi | |
fi | |
} | |
binary () { | |
local binary=$(echo "obase=2;ibase=10;$(($1+(1<<32)))"|bc) | |
printf ${binary:1} | |
} | |
parseflags () { | |
local fbits=$(($1)) | |
local fmask=$(($2)) | |
printf "=========================================================================\n" | |
printf "features:%08X %s\n" $fbits $(binary $fbits) | |
if [[ -z $2 ]]; then | |
fmask=$fbits | |
else | |
printf " mask:%08X %s\n" $fmask $(binary $fmask) | |
fi | |
for isset in printset printunset printignored; do | |
testbit $isset $fbits $fmask 0x00000001 SUPPORTS_CSM_LEGACY_MODE | |
testbit $isset $fbits $fmask 0x00000002 SUPPORTS_CD_DRIVE_BOOT | |
testbit $isset $fbits $fmask 0x00000004 SUPPORTS_TARGET_DISK_MODE | |
testbit $isset $fbits $fmask 0x00000008 UNKNOWN_BIT3 | |
testbit $isset $fbits $fmask 0x00000010 SUPPORTS_NET_BOOT | |
testbit $isset $fbits $fmask 0x00000020 SUPPORTS_SLING_SHOT | |
testbit $isset $fbits $fmask 0x00000040 UNKNOWN_BIT6 | |
testbit $isset $fbits $fmask 0x00000080 UNKNOWN_BIT7 | |
testbit $isset $fbits $fmask 0x00000100 SUPPORTS_WIRELESS | |
testbit $isset $fbits $fmask 0x00000200 UNKNOWN_BIT9 | |
testbit $isset $fbits $fmask 0x00000400 PLATFORM_SECURITY_POLICY_01 | |
testbit $isset $fbits $fmask 0x00000800 PLATFORM_SECURITY_POLICY_02 | |
testbit $isset $fbits $fmask 0x00001000 SUPPORTS_TRB | |
testbit $isset $fbits $fmask 0x00002000 UNKNOWN_BIT13 | |
testbit $isset $fbits $fmask 0x00004000 SUPPORTS_HIGH_SPEED_USB | |
testbit $isset $fbits $fmask 0x00008000 UNKNOWN_BIT15 | |
testbit $isset $fbits $fmask 0x00010000 UNKNOWN_BIT16 | |
testbit $isset $fbits $fmask 0x00020000 DISABLE_USB_SUBSTITUTE_WORKAROUND | |
testbit $isset $fbits $fmask 0x00040000 UNKNOWN_BIT18 | |
testbit $isset $fbits $fmask 0x00080000 SUPPORTS_APFS | |
testbit $isset $fbits $fmask 0x00100000 SUPPORTS_APFS_EXTRA | |
testbit $isset $fbits $fmask 0x00200000 UNKNOWN_BIT21 | |
testbit $isset $fbits $fmask 0x00400000 SUPPORTS_TRBX | |
testbit $isset $fbits $fmask 0x00800000 UNKNOWN_BIT23 | |
testbit $isset $fbits $fmask 0x01000000 SUPPORTS_PLATFORM_SECURITY_POLICY | |
testbit $isset $fbits $fmask 0x02000000 SUPPORTS_EXTENDED_FEATURES | |
testbit $isset $fbits $fmask 0x04000000 UNKNOWN_BIT26 | |
testbit $isset $fbits $fmask 0x08000000 UNKNOWN_BIT27 | |
testbit $isset $fbits $fmask 0x10000000 DISABLE_MBA_S4_WORKAROUND | |
testbit $isset $fbits $fmask 0x20000000 SUPPORTS_UEFI_WINDOWS_BOOT | |
testbit $isset $fbits $fmask 0x40000000 UNKNOWN_BIT30 | |
testbit $isset $fbits $fmask 0x80000000 DISABLE_BOOTSCRIPT_WORKAROUND | |
done | |
} | |
showfirmwarefeatures () { | |
local ExtendedFirmwareFeatures=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') | |
local ExtendedFirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') | |
if [[ -n $ExtendedFirmwareFeatures ]]; then | |
parseflags $ExtendedFirmwareFeatures $ExtendedFirmwareFeaturesMask | |
else | |
local FirmwareFeatures=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') \ | |
local FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') | |
parseflags $FirmwareFeatures $FirmwareFeaturesMask | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment