Last active
October 9, 2023 16:15
-
-
Save joevt/477fe842d16095c2bfd839e2ab4794ff 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
#!/bin/bash | |
# joevt Jun 13, 2023 | |
# https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123 | |
gfxutilrepository="/Volumes/Work/Programming/EFIProjects/gfxutil/joevt-gfxutil" | |
for gfxutilcmd in \ | |
~/Downloads/gfxutil/gfxutil \ | |
~/Downloads/gfxutil \ | |
"$gfxutilrepository/build/Release/gfxutil" \ | |
"$gfxutilrepository/build/Debug/gfxutil" \ | |
"$gfxutilrepository/DerivedData/gfxutil/Build/Products/Debug/gfxutil" \ | |
"" \ | |
; do | |
if [[ -f $gfxutilcmd ]] && file $gfxutilcmd | grep -q "$(uname -m)"; then | |
break | |
fi | |
done | |
if [[ ! -f "$gfxutilcmd" ]]; then | |
echo "# Download and build gfxutil from https://github.com/joevt/gfxutil , then update the path of gfxutil defined in gfxutil.sh" | |
fi | |
alias gfxutil='"$gfxutilcmd"' | |
directblesscmd="/Volumes/Work/Programming/XcodeProjects/bless/bless-204.40.27 joevt/DerivedData/bless/Build/Products/Debug/bless" | |
usedirectbless=0 | |
if [[ -d /System/Library/PrivateFrameworks/APFS.framework/Versions/A ]]; then | |
if [[ ! -f "$directblesscmd" ]]; then | |
echo "# Download and build bless from https://github.com/joevt/bless , then update the path of directbless defined in gfxutil.sh" | |
else | |
usedirectbless=1 | |
fi | |
fi | |
if ((usedirectbless)); then | |
directbless=$directblesscmd | |
alias directbless='"$directbless"' | |
else | |
directbless=bless | |
alias directbless=bless | |
fi | |
pipestatus=( ) # to clear an error in ShellCheck | |
patmatch () { | |
# substitute for [[ =~ ]] for Mac OS X 10.4 | |
perl -0777 -ne '<>; exit !( $_ =~ /'"$1"'/ )' | |
} | |
nvramp () { | |
local thename="$1" | |
local thedata="" # must declare local separately for $? to get the error | |
thedata="$(nvram "$thename")" | |
local theerr=$? | |
# we want to use variables in the printf format string | |
printf "$(sed -E '/^'"$thename"'./s///;s/\\/\\\\/g;s/%([0-9a-f]{2})/\\x\1/g;s/%/%%/g' <<< "$thedata")" | |
return $theerr | |
} | |
efiguid=8BE4DF61-93CA-11D2-AA0D-00E098032B8C | |
ocguid=4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102 | |
dumponebootvar () { | |
local pathonly=0 | |
if [[ $1 == '-p' ]]; then | |
pathonly=1 | |
shift | |
fi | |
local thebootvar="$1" | |
local thebytes="$2" | |
# typedef struct _EFI_LOAD_OPTION | |
local theerr="" | |
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="" | |
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="" | |
theOptionalDatastring=$(xxd -p -r <<< "${theOptionalData}" | iconv -f UTF-16LE -t UTF-8 | tr '\0' '\n' | sed -n -E '1p' | tr -d '\n') | |
if (( pathonly )); then | |
echo "$theFilePathList" | |
else | |
printf "%s %s \"%s\"" "$thebootvar" "$theAttributes" "$theDescription" | |
local parts=0 | |
while [[ -n $theFilePathList ]]; do | |
(( parts++ )) | |
local thepath="" | |
local pathbytes="" | |
thepath=$(gfxutil "$theFilePathList") | |
theerr=$? | |
if (( theerr )); then | |
(( parts == 1 )) && printf " " | |
printf "\"%s\"" "$theFilePathList" | |
theFilePathList="" | |
theerr=0 | |
else | |
(( parts == 1 )) && printf " " | |
printf "\"%s\"" "$thepath" | |
pathbytes=$(gfxutil "$thepath") | |
if patmatch "$pathbytes" <<< "$theFilePathList"; then | |
theFilePathList=${theFilePathList:${#pathbytes}} | |
else | |
printf " # Device path %s does not match %s" "$pathbytes" "$theFilePathList" | |
theFilePathList="" | |
fi | |
fi | |
done | |
[[ -n $theOptionalData ]] && printf " \"%s\"" "$theOptionalDatastring" | |
echo | |
[[ -n $theOptionalData ]] && { | |
printf "%s\n" "$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" | |
} | |
bootvar () { | |
local pathonly="" | |
for ((;;)); do | |
if [[ $1 == '-p' ]]; then | |
pathonly="-p" | |
shift | |
else | |
break | |
fi | |
done | |
local thebootvar="$1" | |
local theguid=$efiguid | |
if patmatch '^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}:' <<< "$thebootvar"; then | |
theguid=${thebootvar:0:36} | |
thebootvar=${thebootvar:37} | |
fi | |
local thebytes="" | |
thebytes="$(nvramp "$theguid:$thebootvar" | xxd -p -c 99999; echo "${pipestatus[1]}${PIPESTATUS[0]}")" | |
local theerr="" | |
theerr=$(sed -n \$p <<< "$thebytes") | |
if (( ! theerr )); then | |
thebytes=$(sed \$d <<< "$thebytes") | |
eval 'dumponebootvar '"$pathonly"' "'"$thebootvar"'" '"$thebytes" | |
theerr=$? | |
fi | |
return "$theerr" | |
} | |
setnvramhex () { | |
sudo nvram "$1=$(sed -E 's/(..)/%\1/g' <<< "${2}")" | |
} | |
setbootvar () { | |
local thebootvar=$1 | |
local theAttributes=$2 | |
local theDescription=$3 | |
local theFilePathList=$4 | |
local theOptionalData=$5 | |
local theAttributesBytes="" | |
theAttributesBytes=$(printf "%08x" "$theAttributes") | |
local theDescriptionBytes="" | |
theDescriptionBytes=$(printf "%s\0" "$theDescription" | iconv -f UTF-8 -t UTF-16LE | xxd -p -c 999999) | |
local theFilePathListBytes="" | |
local thepat='^([a-z0-9]{2})*7fff0400$' | |
if patmatch "$thepat" <<< "$theFilePathList"; then | |
theFilePathListBytes="$theFilePathList" | |
elif [[ -e $theFilePathList ]]; then | |
theFilePathListBytes=$(getefipath "$theFilePathList") | |
else | |
theFilePathListBytes=$(gfxutil "$theFilePathList") | |
fi | |
local theFilePathListLength=$((${#theFilePathListBytes} / 2)) | |
local theFilePathListLengthBytes=0 | |
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}" | |
local theguid=$efiguid | |
if patmatch '^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}:' <<< "$thebootvar"; then | |
theguid=${thebootvar:0:36} | |
thebootvar=${thebootvar:38} | |
fi | |
setnvramhex "${theguid}:${thebootvar}" "${thebytes}" | |
} | |
setbootorder () { | |
IFS='' | |
local theguid=$efiguid | |
local thestring="$*" | |
sudo nvram "${theguid}: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 theguid in $efiguid; do | |
local theboot="" | |
for theboot in Current Next; do | |
local BootWhat="" | |
BootWhat=$(nvramp "$theguid:Boot$theboot" 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g') | |
echo "Boot$theboot: $BootWhat" | |
done | |
local Timeout="" | |
Timeout=$((0x$(nvramp "$theguid:Timeout" 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/\2\1/g'))) | |
echo "Timeout: ${Timeout}s" | |
echo | |
local needlinefeed=0 | |
local theType="" | |
for theType in Boot Driver; do | |
local BootOrder="" | |
BootOrder=$(nvramp "$theguid:${theType}Order" 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'"${theType}"'\2\1 /g;/ $/s///') | |
echo "${theType}Order: $BootOrder" | |
IFS=$' ' | |
for theboot in $(printf "%s" "$BootOrder"); do | |
bootvar "${theguid}:${theboot}" 2> /dev/null | |
done | |
#echo "Search loop" | |
IFS=$'\n' | |
local lowboot=-1 | |
local boot="" | |
for boot in $( { | |
eval "$(nvramp "$theguid:${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 | |
if ((needlinefeed)); then | |
printf ", " | |
else | |
printf "#Searching: " | |
fi | |
printf "%s" "$thebootvar($inc)" | |
needlinefeed=1 | |
first=0 | |
fi | |
local bootinfo="" | |
bootinfo="$(bootvar "${theguid}:${thebootvar}" 2> /dev/null)" | |
local theerr=$? | |
if ((theerr)); then | |
break | |
fi | |
if ((needlinefeed)); then | |
echo | |
needlinefeed=0 | |
fi | |
printf "%s\n" "$bootinfo" | |
((boot+=inc)) | |
done | |
((inc < 0)) && ((lowboot = boot)) | |
done | |
if ((needlinefeed)); then | |
echo | |
needlinefeed=0 | |
fi | |
echo | |
done | |
done | |
} | |
getefipath () { | |
# Takes a path to a file or directory or volume and outputs the EFI device path in hex. | |
# Note: Overwrites BootNext | |
local thefile="$1" | |
local theguid=$efiguid | |
# First, get current boot vars | |
local BootOrderValue="" | |
BootOrderValue=$(nvramp $theguid:BootOrder 2> /dev/null | xxd -u -p -c 99999) | |
local BootOrder="" | |
BootOrder=$(sed -E 's/(..)(..)/Boot\2\1 /g;/ $/s///' <<< "$BootOrderValue") | |
eval "$(sed -E 's/(..)(..)/local Boot\2\1=''$''(nvramp '"$theguid"':Boot\2\1 2> \/dev\/null | xxd -u -p -c 99999) ; /g' <<< "$BootOrderValue")" | |
# We won't try to preserve BootNext - that would require preserving efi-boot-next-data | |
#local BootNextValue="" | |
#local BootNextName="" | |
#BootNextValue=$(nvramp $theguid:BootNext 2> /dev/null | xxd -u -p -c 99999) | |
#BootNextName="Boot${BootNextValue:2:2}${BootNextValue:0:2}" | |
# Use bless to convert file path to EFI device path - this affects BootNext and one of the boot vars | |
if ( sudo "$directbless" --mount "$thefile" --file "$thefile" --nextonly --setBoot ); then | |
local thebootvar="" | |
thebootvar=$(nvramp $theguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g') | |
local thepath="" | |
thepath=$(bootvar -p "${theguid}:${thebootvar}" 2> /dev/null) | |
local theerr=$? | |
if (( theerr == 0 )); then | |
# if one of the existing boot vars was affected, then restore it | |
if patmatch "$thebootvar" <<< "$BootOrder"; then | |
setnvramhex "$theguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")" | |
fi | |
# output the result | |
printf "%s" "$thepath" | |
else | |
echo "# BootNext:$thebootvar not set" 1>&2 | |
return 1 | |
fi | |
# cleanup BootNext | |
sudo nvram -d $theguid:BootNext | |
sudo nvram -d efi-boot-next-data | |
else | |
echo '# This bless command failed:' 1>&2 | |
echo '# sudo "'"$directbless"'" --mount "'"$thefile"'" --file "'"$thefile"'" --nextonly --setBoot' 1>&2 | |
return 1 | |
fi | |
return 0 | |
} | |
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//printf "%s = " "\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 | |
} | |
convertnvramstring () { | |
local thevar="$1" | |
local thevar="$2" | |
# we want to use variables in the printf format string | |
printf "$(printf "%s" "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')" | |
} | |
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 | |
convertnvramstring "$thevar" "$theval" | |
((i++)) | |
done | |
} | |
setaaplpathprops () { | |
local thefile="$1" | |
local theproperties="" | |
theproperties=$(xxd -p -c 99999 "$1") | |
local thevar=0 | |
while ((1)); do | |
local thepart=${theproperties:$thevar*768*2:768*2} | |
local thename="" | |
thename="4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:AAPL,PathProperties"$(printf "%04X" thevar) | |
if [[ -n $thepart ]]; then | |
sudo nvram "${thename}=$(sed -E 's/(..)/%\1/g' <<< "${thepart}")" | |
elif nvram "${thename}" > /dev/null 2>&1; then | |
sudo nvram -d "$thename" | |
else | |
break | |
fi | |
((thevar++)) | |
done | |
} | |
getpanic () { | |
# Get panic log 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 | |
convertnvramstring "$thevar" "$theval" | |
((i++)) | |
done | |
} | |
getpanic2 () { | |
# panic log 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 | |
convertnvramstring "$thevar" "$theval" | |
((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 "%s" "$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 %s" "$fname" | |
printf "\n" | |
fi | |
fi | |
elif [[ $isset = "printignored" ]]; then | |
if ((!(fbit & fmask))); then | |
printf "ignore %s" "$fname" | |
printf "\n" | |
fi | |
fi | |
} | |
GetNum64 () { | |
local thenum="$1" | |
printf "%s" $(( (0x${thenum:0:1} << 60) | 0x${thenum:1} )) | |
} | |
binary () { | |
local thenum="$1" # input decimal number | |
local numbits="$2" | |
local binary="" | |
binary=$(bc <<< "obase=2;ibase=10;$thenum") | |
printf "%${numbits}s" "${binary}" | tr ' ' '0' | |
} | |
parseflags () { | |
local fbits=$(($1)) | |
local fmask=$(($2)) | |
local numbits=$(($3)) | |
local numhex=$(((numbits + 3) / 4)) | |
printf "=========================================================================\n" | |
if ((numbits > 32)); then | |
echo ExtendedFirmwareFeatures | |
else | |
echo FirmwareFeatures | |
fi | |
printf "features:%0${numhex}X %s\n" $fbits "$(binary $fbits $numbits)" | |
if [[ -z $2 ]]; then | |
fmask=$fbits | |
else | |
printf " mask:%0${numhex}X %s\n" $fmask "$(binary "$(printf "%u" $fmask)" $numbits)" | |
fi | |
local isset="" | |
for isset in printset printunset printignored; do | |
#https://github.com/acidanthera/OpenCorePkg/blob/master/Include/Apple/IndustryStandard/AppleFeatures.h | |
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 | |
testbit $isset $fbits $fmask 0x800000000 SUPPORTS_LARGE_BASESYSTEM | |
done | |
} | |
showfirmwarefeatures () { | |
local ExtendedFirmwareFeatures="" | |
ExtendedFirmwareFeatures=$(GetNum64 "$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//\1/')") | |
local ExtendedFirmwareFeaturesMask="" | |
ExtendedFirmwareFeaturesMask=$(GetNum64 "$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//\1/')") | |
if [[ -n $ExtendedFirmwareFeatures ]]; then | |
parseflags "$ExtendedFirmwareFeatures" "$ExtendedFirmwareFeaturesMask" 36 | |
fi | |
local FirmwareFeatures="" | |
FirmwareFeatures=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') | |
local FirmwareFeaturesMask="" | |
FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/') | |
if [[ -n $FirmwareFeatures ]]; then | |
parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask" 32 | |
fi | |
} |
Update 1:
- Can now pass volume or directory or file path to
setbootvar
. See examples in first comment.
Jun 5, 2021:
- getefipath now ensures that the boot order variables are not modified (but BootNext is still deleted).
Aug 22, 2021:
- Sometimes a bootvar has multiple UEFI device paths so we'll try to list them all.
- Use printf because echo might do weird stuff with some back-slashes (e.g. \b is backspace).
Oct 11, 2021:
- Add SUPPORTS_LARGE_BASESYSTEM firmware features flag.
- Check if gfxutil was downloaded to a folder.
- Correctly output features and feature masks that are greater than 32 bit.
- Output both features and extended features.
Dec 24, 2021:
- Add some Mac OS X 10.4 compatibility.
- Fix directbless check.
- If gfxutil can't get a device path then at least dump the hex for the bootvar.
Mar 5, 2023:
bootvar
andsetbootvar
can work with Boot#### variables from a specific guid instead of just the default EFI guid. For example, Open Core has its own copy of Boot#### variables which you can get using$ocguid
- Use workaround
GetNum64
to parse 64-bit unsigned numbers so thatshowfirmwarefeatures
shows all 64 bits of theExtendedFirmwareFeatures
mask instead of just 60 bits. Don't use the shell to parsethenum
in thebinary
method; letbc
handle the unparsed value since it won't complain about overflow.
Jun 12, 2023:
dumponebootvar
parses a hex string as a bootvar.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Download
Install (temporarily)
Set some EFI drivers
This is an example. If you have EFI drivers to load, they will be different than these. If you don't want to load EFI drivers, then don't do this.
List the Boot#### and Driver#### variables