Skip to content

Instantly share code, notes, and snippets.

@DigiMiZi
Forked from joevt/gfxutil.sh
Created September 14, 2025 17:30
Show Gist options
  • Select an option

  • Save DigiMiZi/d731bb291fa7d11f0dce192a95ac82d5 to your computer and use it in GitHub Desktop.

Select an option

Save DigiMiZi/d731bb291fa7d11f0dce192a95ac82d5 to your computer and use it in GitHub Desktop.

Revisions

  1. @joevt joevt revised this gist Jun 12, 2023. 1 changed file with 100 additions and 74 deletions.
    174 changes: 100 additions & 74 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,17 @@
    #!/bin/bash
    # joevt Mar 5, 2023
    # 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/DerivedData/gfxutil/Build/Products/Debug/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
    if [[ -f $gfxutilcmd ]] && file $gfxutilcmd | grep -q "$(uname -m)"; then
    break
    fi
    done
    @@ -51,18 +52,86 @@ nvramp () {
    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

    bootvar () {
    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=1
    pathonly="-p"
    shift
    else
    break
    @@ -78,64 +147,13 @@ bootvar () {
    fi

    local thebytes=""
    thebytes="$(nvramp $theguid:"$thebootvar" | xxd -p -c 99999; echo "${pipestatus[1]}${PIPESTATUS[0]}")"
    # typedef struct _EFI_LOAD_OPTION
    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")

    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
    eval 'dumponebootvar '"$pathonly"' "'"$thebootvar"'" '"$thebytes"
    theerr=$?
    fi
    return "$theerr"
    }
    @@ -195,22 +213,22 @@ dumpallbootvars () {
    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')
    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')))
    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///')
    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 $(echo "$BootOrder"); do
    for theboot in $(printf "%s" "$BootOrder"); do
    bootvar "${theguid}:${theboot}" 2> /dev/null
    done

    @@ -219,7 +237,7 @@ dumpallbootvars () {
    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
    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"
    @@ -280,7 +298,7 @@ getefipath () {
    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")"
    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=""
    @@ -312,7 +330,8 @@ getefipath () {
    sudo nvram -d $theguid:BootNext
    sudo nvram -d efi-boot-next-data
    else
    echo '# Bless failed' 1>&2
    echo '# This bless command failed:' 1>&2
    echo '# sudo "'"$directbless"'" --mount "'"$thefile"'" --file "'"$thefile"'" --nextonly --setBoot' 1>&2
    return 1
    fi
    return 0
    @@ -338,6 +357,13 @@ 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)
    @@ -346,7 +372,7 @@ getaaplpathprops () {
    thevar="4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:AAPL,PathProperties$(printf "%04X" $i)"
    theval="$(nvram "$thevar" 2> /dev/null)"
    [[ -z $theval ]] && break
    printf "$(printf "%s" "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    convertnvramstring "$thevar" "$theval"
    ((i++))
    done
    }
    @@ -379,7 +405,7 @@ getpanic () {
    thevar="AAPL,PanicInfo000$(printf "%02x" $((0x$(printf 'K' | xxd -p) + i)) | xxd -p -r)"
    theval="$(nvram "$thevar" 2> /dev/null)"
    [[ -z $theval ]] && break
    printf "$(printf "%s" "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    convertnvramstring "$thevar" "$theval"
    ((i++))
    done
    }
    @@ -392,7 +418,7 @@ getpanic2 () {
    thevar="aapl,panic-info"
    theval="$(nvram "$thevar" 2> /dev/null)"
    [[ -z $theval ]] && break
    printf "$(printf "%s" "$theval" | sed -E '/^'$thevar'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    convertnvramstring "$thevar" "$theval"
    ((i++))
    break
    done
    @@ -416,7 +442,7 @@ testbit () {
    fi
    elif [[ $isset = "printunset" ]]; then
    if ((!(fbit & fbits))); then
    if (((fbit & fmask))); then
    if ((fbit & fmask)); then
    printf "not %s" "$fname"
    printf "\n"
    fi
    @@ -431,7 +457,7 @@ testbit () {

    GetNum64 () {
    local thenum="$1"
    printf $(( (0x${thenum:0:1} << 60) | 0x${thenum:1} ))
    printf "%s" $(( (0x${thenum:0:1} << 60) | 0x${thenum:1} ))
    }

    binary () {
    @@ -458,7 +484,7 @@ parseflags () {
    if [[ -z $2 ]]; then
    fmask=$fbits
    else
    printf " mask:%0${numhex}X %s\n" $fmask "$(binary $(printf "%u" $fmask) $numbits)"
    printf " mask:%0${numhex}X %s\n" $fmask "$(binary "$(printf "%u" $fmask)" $numbits)"
    fi
    local isset=""
    for isset in printset printunset printignored; do
    @@ -501,9 +527,9 @@ parseflags () {

    showfirmwarefeatures () {
    local ExtendedFirmwareFeatures=""
    ExtendedFirmwareFeatures=$(GetNum64 $(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//\1/'))
    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/'))
    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
  2. @joevt joevt revised this gist Mar 6, 2023. 1 changed file with 148 additions and 120 deletions.
    268 changes: 148 additions & 120 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #!/bin/bash
    # joevt Dec 24, 2021
    # joevt Mar 5, 2023
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilrepository="/Volumes/Work/Programming/EFIProjects/gfxutil/joevt-gfxutil"
    @@ -56,17 +56,29 @@ nvramp () {
    }

    efiguid=8BE4DF61-93CA-11D2-AA0D-00E098032B8C
    ocguid=4D1FDA02-38C7-4A6A-9CC6-4BCCA8B30102

    bootvar () {
    local pathonly=0
    if [[ $1 == '-p' ]]; then
    pathonly=1
    shift
    fi
    for ((;;)); do
    if [[ $1 == '-p' ]]; then
    pathonly=1
    shift
    else
    break
    fi
    done

    local thebootvar=$1
    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 $efiguid:"$thebootvar" | xxd -p -c 99999; echo "${pipestatus[1]}${PIPESTATUS[0]}")"
    thebytes="$(nvramp $theguid:"$thebootvar" | xxd -p -c 99999; echo "${pipestatus[1]}${PIPESTATUS[0]}")"
    # typedef struct _EFI_LOAD_OPTION
    local theerr=""
    theerr=$(sed -n \$p <<< "$thebytes")
    @@ -157,13 +169,19 @@ setbootvar () {

    local thebytes="${theAttributesBytes:6:2}${theAttributesBytes:4:2}${theAttributesBytes:2:2}${theAttributesBytes:0:2}${theFilePathListLengthBytes:2:2}${theFilePathListLengthBytes:0:2}${theDescriptionBytes}${theFilePathListBytes}${theOptionalData}"

    setnvramhex "${efiguid}:${thebootvar}" "${thebytes}"
    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 "${efiguid}:BootOrder=$(sed -E "s/[Bb]oot//g;s/(..)(..)/%\2%\1/g" <<< "$thestring")"
    sudo nvram "${theguid}:BootOrder=$(sed -E "s/[Bb]oot//g;s/(..)(..)/%\2%\1/g" <<< "$thestring")"
    }

    setdriverorder () {
    @@ -173,78 +191,80 @@ setdriverorder () {
    }

    dumpallbootvars () {
    local theboot=""
    for theboot in Current Next; do
    local BootWhat=""
    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
    local Timeout=""
    Timeout=$((0x$(nvramp $efiguid: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 $efiguid:${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 $(echo "$BootOrder"); do
    bootvar "$theboot" 2> /dev/null
    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

    #echo "Search loop"
    IFS=$'\n'
    local lowboot=-1
    local boot=""
    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
    if ((needlinefeed)); then
    printf ", "
    else
    printf "#Searching: "
    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 $(echo "$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
    printf "%s" "$thebootvar($inc)"
    needlinefeed=1
    first=0
    fi

    local bootinfo=""
    bootinfo="$(bootvar "$thebootvar" 2> /dev/null)"
    local theerr=$?
    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))
    if ((theerr)); then
    break
    fi
    if ((needlinefeed)); then
    echo
    needlinefeed=0
    fi
    printf "%s\n" "$bootinfo"
    ((boot+=inc))
    done
    ((inc < 0)) && ((lowboot = boot))
    done
    ((inc < 0)) && ((lowboot = boot))
    done
    if ((needlinefeed)); then
    if ((needlinefeed)); then
    echo
    needlinefeed=0
    fi
    echo
    needlinefeed=0
    fi
    echo
    done
    done
    }

    @@ -253,31 +273,33 @@ getefipath () {
    # Note: Overwrites BootNext
    local thefile="$1"

    local theguid=$efiguid

    # First, get current boot vars
    local BootOrderValue=""
    BootOrderValue=$(nvramp $efiguid:BootOrder 2> /dev/null | xxd -u -p -c 99999)
    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 '"$efiguid"':Boot\2\1 2> \/dev\/null | xxd -u -p -c 99999) ; /g' <<< "$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 $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999)
    #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 $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g')
    thebootvar=$(nvramp $theguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g')
    local thepath=""
    thepath=$(bootvar -p "$thebootvar" 2> /dev/null)
    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 "$efiguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")"
    setnvramhex "$theguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")"
    fi
    # output the result
    printf "%s" "$thepath"
    @@ -287,7 +309,7 @@ getefipath () {
    fi

    # cleanup BootNext
    sudo nvram -d $efiguid:BootNext
    sudo nvram -d $theguid:BootNext
    sudo nvram -d efi-boot-next-data
    else
    echo '# Bless failed' 1>&2
    @@ -350,7 +372,7 @@ setaaplpathprops () {
    }

    getpanic () {
    # Get device properties from nvram AAPL,PanicInfo000K,000M,etc.
    # Get panic log from nvram AAPL,PanicInfo000K,000M,etc.
    # (max 768 per nvram var)
    i=0
    while (( 1 )); do
    @@ -363,7 +385,7 @@ getpanic () {
    }

    getpanic2 () {
    # Get device properties from nvram aapl,panic-info
    # panic log from nvram aapl,panic-info
    # (max 768 per nvram var)
    i=0
    while (( 1 )); do
    @@ -407,11 +429,16 @@ testbit () {
    fi
    }

    binary () {
    GetNum64 () {
    local thenum="$1"
    printf $(( (0x${thenum:0:1} << 60) | 0x${thenum:1} ))
    }

    binary () {
    local thenum="$1" # input decimal number
    local numbits="$2"
    local binary=""
    binary=$(echo "obase=2;ibase=10;$(($thenum))"|bc)
    binary=$(bc <<< "obase=2;ibase=10;$thenum")
    printf "%${numbits}s" "${binary}" | tr ' ' '0'
    }

    @@ -431,51 +458,52 @@ parseflags () {
    if [[ -z $2 ]]; then
    fmask=$fbits
    else
    printf " mask:%0${numhex}X %s\n" $fmask "$(binary $fmask $numbits)"
    printf " mask:%0${numhex}X %s\n" $fmask "$(binary $(printf "%u" $fmask) $numbits)"
    fi
    local isset=""
    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
    #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=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    ExtendedFirmwareFeatures=$(GetNum64 $(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//\1/'))
    local ExtendedFirmwareFeaturesMask=""
    ExtendedFirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    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
  3. @joevt joevt revised this gist Dec 24, 2021. 1 changed file with 43 additions and 20 deletions.
    63 changes: 43 additions & 20 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,21 +1,31 @@
    #!/bin/bash
    # joevt Oct 11, 2021
    # joevt Dec 24, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil/gfxutil
    if [[ ! -f $gfxutilcmd ]]; then
    gfxutilcmd=~/Downloads/gfxutil
    fi
    if [[ ! -f $gfxutilcmd ]]; then
    gfxutilcmd="/Volumes/Work/Programming/EFIProjects/gfxutil/joevt-gfxutil/DerivedData/gfxutil/Build/Products/Debug/gfxutil"
    gfxutilrepository="/Volumes/Work/Programming/EFIProjects/gfxutil/joevt-gfxutil"
    for gfxutilcmd in \
    ~/Downloads/gfxutil/gfxutil \
    ~/Downloads/gfxutil \
    "$gfxutilrepository/DerivedData/gfxutil/Build/Products/Debug/gfxutil" \
    "$gfxutilrepository/build/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/APFS ]]; then
    if [[ ! -f "$directbless" ]]; then
    echo "# Download and build bless from https://github.com/joevt/bless , then update the path of directbless defined in DiskUtil.sh"
    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
    @@ -31,12 +41,17 @@ 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=$?
    printf "$(sed -E '/^'"$thename"'./s///;s/\\/\\\\/g;s/%/\\x/g' <<< "$thedata")"
    printf "$(sed -E '/^'"$thename"'./s///;s/\\/\\\\/g;s/%([0-9a-f]{2})/\\x\1/g;s/%/%%/g' <<< "$thedata")"
    return $theerr
    }

    @@ -85,14 +100,22 @@ bootvar () {
    local thepath=""
    local pathbytes=""
    thepath=$(gfxutil "$theFilePathList")
    (( parts == 1 )) && printf " "
    printf "\"%s\"" "$thepath"
    pathbytes=$(gfxutil "$thepath")
    if [[ $theFilePathList =~ $pathbytes ]]; then
    theFilePathList=${theFilePathList:${#pathbytes}}
    else
    printf " # Device path %s does not match %s" "$pathbytes" "$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"
    @@ -121,7 +144,7 @@ setbootvar () {
    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 [[ $theFilePathList =~ $thepat ]]; then
    if patmatch "$thepat" <<< "$theFilePathList"; then
    theFilePathListBytes="$theFilePathList"
    elif [[ -e $theFilePathList ]]; then
    theFilePathListBytes=$(getefipath "$theFilePathList")
    @@ -253,7 +276,7 @@ getefipath () {

    if (( theerr == 0 )); then
    # if one of the existing boot vars was affected, then restore it
    if [[ $BootOrder =~ $thebootvar ]]; then
    if patmatch "$thebootvar" <<< "$BootOrder"; then
    setnvramhex "$efiguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")"
    fi
    # output the result
  4. @joevt joevt revised this gist Oct 11, 2021. 1 changed file with 24 additions and 12 deletions.
    36 changes: 24 additions & 12 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -385,20 +385,30 @@ testbit () {
    }

    binary () {
    local thenum="$1"
    local numbits="$2"
    local binary=""
    binary=$(echo "obase=2;ibase=10;$(($1+(1<<32)))"|bc)
    printf "%s" "${binary:1}"
    binary=$(echo "obase=2;ibase=10;$(($thenum))"|bc)
    printf "%${numbits}s" "${binary}" | tr ' ' '0'
    }

    parseflags () {
    local fbits=$(($1))
    local fmask=$(($2))
    local numbits=$(($3))
    local numhex=$(((numbits + 3) / 4))
    printf "=========================================================================\n"
    printf "features:%08X %s\n" $fbits "$(binary $fbits)"
    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:%08X %s\n" $fmask "$(binary $fmask)"
    printf " mask:%0${numhex}X %s\n" $fmask "$(binary $fmask $numbits)"
    fi
    local isset=""
    for isset in printset printunset printignored; do
    @@ -443,14 +453,16 @@ showfirmwarefeatures () {
    ExtendedFirmwareFeatures=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    local ExtendedFirmwareFeaturesMask=""
    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=""
    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/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    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
    }
  5. @joevt joevt revised this gist Oct 11, 2021. 1 changed file with 10 additions and 3 deletions.
    13 changes: 10 additions & 3 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,14 @@
    #!/bin/bash
    # joevt Aug 22, 2021
    # joevt Oct 11, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    gfxutilcmd=~/Downloads/gfxutil/gfxutil
    if [[ ! -f $gfxutilcmd ]]; then
    gfxutilcmd=~/Downloads/gfxutil
    fi
    if [[ ! -f $gfxutilcmd ]]; then
    gfxutilcmd="/Volumes/Work/Programming/EFIProjects/gfxutil/joevt-gfxutil/DerivedData/gfxutil/Build/Products/Debug/gfxutil"
    fi
    alias gfxutil='"$gfxutilcmd"'

    directblesscmd="/Volumes/Work/Programming/XcodeProjects/bless/bless-204.40.27 joevt/DerivedData/bless/Build/Products/Debug/bless"
    @@ -428,6 +434,7 @@ parseflags () {
    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
    }

    @@ -446,4 +453,4 @@ showfirmwarefeatures () {
    FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    fi
    }
    }
  6. @joevt joevt revised this gist Aug 23, 2021. 1 changed file with 26 additions and 13 deletions.
    39 changes: 26 additions & 13 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #!/bin/bash
    # joevt Jun 5, 2021
    # joevt Aug 22, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    @@ -72,14 +72,27 @@ bootvar () {
    if (( pathonly )); then
    echo "$theFilePathList"
    else
    echo -n "$thebootvar $theAttributes "'"'"$theDescription"'"'
    [[ -n $theFilePathList ]] && {
    echo -n ' "'; gfxutil "$theFilePathList" | cat; echo -n '"'
    }
    [[ -n $theOptionalData ]] && echo -n " "'"'"$theOptionalDatastring"'"'
    printf "%s %s \"%s\"" "$thebootvar" "$theAttributes" "$theDescription"
    local parts=0
    while [[ -n $theFilePathList ]]; do
    (( parts++ ))
    local thepath=""
    local pathbytes=""
    thepath=$(gfxutil "$theFilePathList")
    (( parts == 1 )) && printf " "
    printf "\"%s\"" "$thepath"
    pathbytes=$(gfxutil "$thepath")
    if [[ $theFilePathList =~ $pathbytes ]]; then
    theFilePathList=${theFilePathList:${#pathbytes}}
    else
    printf " # Device path %s does not match %s" "$pathbytes" "$theFilePathList"
    theFilePathList=""
    fi
    done
    [[ -n $theOptionalData ]] && printf " \"%s\"" "$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/"
    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
    fi
    @@ -238,7 +251,7 @@ getefipath () {
    setnvramhex "$efiguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")"
    fi
    # output the result
    echo -n "$thepath"
    printf "%s" "$thepath"
    else
    echo "# BootNext:$thebootvar not set" 1>&2
    return 1
    @@ -261,7 +274,7 @@ dumpallioregefipaths () {
    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/'
    ' | sed -E '/device-properties/d;/(.*) = <(.*)>/s//printf "%s = " "\1"; gfxutil \2 | cat; echo/'
    )"
    }

    @@ -282,7 +295,7 @@ getaaplpathprops () {
    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')"
    printf "$(printf "%s" "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    ((i++))
    done
    }
    @@ -315,7 +328,7 @@ getpanic () {
    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')"
    printf "$(printf "%s" "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    ((i++))
    done
    }
    @@ -328,7 +341,7 @@ getpanic2 () {
    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')"
    printf "$(printf "%s" "$theval" | sed -E '/^'$thevar'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    ((i++))
    break
    done
    @@ -433,4 +446,4 @@ showfirmwarefeatures () {
    FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    fi
    }
    }
  7. @joevt joevt revised this gist Jun 5, 2021. 1 changed file with 43 additions and 9 deletions.
    52 changes: 43 additions & 9 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,14 +1,23 @@
    #!/bin/bash
    # joevt Mar 10, 2021
    # joevt Jun 5, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    alias gfxutil='"$gfxutilcmd"'

    directbless="/Volumes/Work/Programming/XcodeProjects/bless/bless-204.40.27 joevt/DerivedData/bless/Build/Products/Debug/bless"
    alias directbless='"$directbless"'
    if [[ ! -f "$directbless" ]]; then
    echo "# Download and build bless from https://github.com/joevt/bless , then update the path of directbless defined in gfxutil.sh"
    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/APFS ]]; then
    if [[ ! -f "$directbless" ]]; then
    echo "# Download and build bless from https://github.com/joevt/bless , then update the path of directbless defined in DiskUtil.sh"
    else
    usedirectbless=1
    fi
    fi
    if ((usedirectbless)); then
    directbless=$directblesscmd
    alias directbless='"$directbless"'
    else
    directbless=bless
    alias directbless=bless
    fi
    @@ -122,9 +131,10 @@ setdriverorder () {
    }

    dumpallbootvars () {
    local theboot=""
    for theboot in Current Next; do
    local BootWhat=""
    BootWhat=$(nvramp $efiguid:Boot$theboot 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1 /g')
    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
    local Timeout=""
    @@ -133,6 +143,7 @@ dumpallbootvars () {
    echo

    local needlinefeed=0
    local theType=""
    for theType in Boot Driver; do
    local BootOrder=""
    BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'"${theType}"'\2\1 /g;/ $/s///')
    @@ -145,6 +156,7 @@ dumpallbootvars () {
    #echo "Search loop"
    IFS=$'\n'
    local lowboot=-1
    local boot=""
    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
    @@ -165,7 +177,7 @@ dumpallbootvars () {
    else
    printf "#Searching: "
    fi
    printf "$thebootvar($inc)"
    printf "%s" "$thebootvar($inc)"
    needlinefeed=1
    first=0
    fi
    @@ -198,20 +210,41 @@ 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"

    # First, get current boot vars
    local BootOrderValue=""
    BootOrderValue=$(nvramp $efiguid: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 '"$efiguid"':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 $efiguid: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 $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g')
    local thepath=""
    thepath=$(bootvar -p "$thebootvar" 2> /dev/null)
    local theerr=$?

    if (( theerr == 0 )); then
    # if one of the existing boot vars was affected, then restore it
    if [[ $BootOrder =~ $thebootvar ]]; then
    setnvramhex "$efiguid:$thebootvar" "$(eval 'echo $'"${thebootvar}")"
    fi
    # output the result
    echo -n "$thepath"
    else
    echo "# BootNext:$thebootvar not set" 1>&2
    return 1
    fi

    # cleanup BootNext
    sudo nvram -d $efiguid:BootNext
    sudo nvram -d efi-boot-next-data
    else
    @@ -348,6 +381,7 @@ parseflags () {
    else
    printf " mask:%08X %s\n" $fmask "$(binary $fmask)"
    fi
    local isset=""
    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
    @@ -399,4 +433,4 @@ showfirmwarefeatures () {
    FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    fi
    }
    }
  8. @joevt joevt revised this gist Mar 11, 2021. 1 changed file with 34 additions and 8 deletions.
    42 changes: 34 additions & 8 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    #!/bin/bash
    # joevt Jan 31, 2021
    # joevt Mar 10, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    @@ -63,11 +63,11 @@ bootvar () {
    if (( pathonly )); then
    echo "$theFilePathList"
    else
    echo -n "$thebootvar: $theAttributes, "'"'"$theDescription"'"'
    echo -n "$thebootvar $theAttributes "'"'"$theDescription"'"'
    [[ -n $theFilePathList ]] && {
    echo -n ', "'; gfxutil "$theFilePathList" | cat; echo -n '"'
    echo -n ' "'; gfxutil "$theFilePathList" | cat; echo -n '"'
    }
    [[ -n $theOptionalData ]] && echo -n ", "'"'"$theOptionalDatastring"'"'
    [[ -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/"
    @@ -127,11 +127,15 @@ dumpallbootvars () {
    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
    local Timeout=""
    Timeout=$((0x$(nvramp $efiguid:Timeout 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/\2\1/g')))
    echo "Timeout: ${Timeout}s"
    echo

    local needlinefeed=0
    for theType in Boot Driver; do
    local BootOrder=""
    BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'"${theType}"'\2\1 /g')
    BootOrder=$(nvramp $efiguid:${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 $(echo "$BootOrder"); do
    @@ -156,14 +160,36 @@ dumpallbootvars () {
    ((boot > lowboot)) || break
    ((inc > 0)) && ((lowboot = boot))
    if ((first)); then
    echo "Searching: $thebootvar"
    if ((needlinefeed)); then
    printf ", "
    else
    printf "#Searching: "
    fi
    printf "$thebootvar($inc)"
    needlinefeed=1
    first=0
    fi
    bootvar "$thebootvar" 2> /dev/null || break

    local bootinfo=""
    bootinfo="$(bootvar "$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
    }
    @@ -373,4 +399,4 @@ showfirmwarefeatures () {
    FirmwareFeaturesMask=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:FirmwareFeaturesMask 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    fi
    }
    }
  9. @joevt joevt revised this gist Feb 1, 2021. 1 changed file with 12 additions and 4 deletions.
    16 changes: 12 additions & 4 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,19 @@
    #!/bin/bash
    # joevt Jan 29, 2021
    # joevt Jan 31, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil

    alias gfxutil='"$gfxutilcmd"'

    directbless="/Volumes/Work/Programming/XcodeProjects/bless/bless-204.40.27 joevt/DerivedData/bless/Build/Products/Debug/bless"
    alias directbless='"$directbless"'
    if [[ ! -f "$directbless" ]]; then
    echo "# Download and build bless from https://github.com/joevt/bless , then update the path of directbless defined in gfxutil.sh"
    directbless=bless
    alias directbless=bless
    fi


    pipestatus=( ) # to clear an error in ShellCheck

    nvramp () {
    @@ -126,7 +134,7 @@ dumpallbootvars () {
    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 $(<<< "$BootOrder"); do
    for theboot in $(echo "$BootOrder"); do
    bootvar "$theboot" 2> /dev/null
    done

    @@ -164,7 +172,7 @@ 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"
    if ( sudo bless --mount "$thefile" --file "$thefile" --nextonly --setBoot ); then
    if ( sudo "$directbless" --mount "$thefile" --file "$thefile" --nextonly --setBoot ); then
    local thebootvar=""
    thebootvar=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g')
    local thepath=""
  10. @joevt joevt revised this gist Jan 29, 2021. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -2,8 +2,7 @@
    # joevt Jan 29, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd="/Volumes/Work/Programming/EFIProjects/gfxutil-1.80b_joevt3/DerivedData/gfxutil/Build/Products/Release/gfxutil"
    #gfxutilcmd=~/Downloads/gfxutil
    gfxutilcmd=~/Downloads/gfxutil

    alias gfxutil='"$gfxutilcmd"'

  11. @joevt joevt revised this gist Jan 29, 2021. 1 changed file with 124 additions and 58 deletions.
    182 changes: 124 additions & 58 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,27 +1,39 @@
    # joevt Dec 30, 2020
    #!/bin/bash
    # joevt Jan 29, 2021
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    gfxutilcmd="/Volumes/Work/Programming/EFIProjects/gfxutil-1.80b_joevt3/DerivedData/gfxutil/Build/Products/Release/gfxutil"
    #gfxutilcmd=~/Downloads/gfxutil

    alias gfxutil="'$gfxutilcmd'"
    alias gfxutil='"$gfxutilcmd"'

    pipestatus=( ) # to clear an error in ShellCheck

    nvramp () {
    local thename="$1"
    local thedata="" # must declare local separately for $? to get the error
    thedata="$(nvram $thename)"
    thedata="$(nvram "$thename")"
    local theerr=$?
    printf "$(sed -E '/^'$thename'./s///;s/\\/\\\\/g;s/%/\\x/g' <<< "$thedata")"
    printf "$(sed -E '/^'"$thename"'./s///;s/\\/\\\\/g;s/%/\\x/g' <<< "$thedata")"
    return $theerr
    }

    efiguid=8BE4DF61-93CA-11D2-AA0D-00E098032B8C

    bootvar () {
    local pathonly=0
    if [[ $1 == '-p' ]]; then
    pathonly=1
    shift
    fi

    local thebootvar=$1
    local thebytes="$(nvramp $efiguid:"$thebootvar" | xxd -p -c 99999; echo ${pipestatus[1]}${PIPESTATUS[0]})"
    local thebytes=""
    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
    local theerr=""
    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}))
    @@ -33,23 +45,33 @@ bootvar () {
    # 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 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=$(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/"
    }
    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
    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
    fi
    return $theerr
    return "$theerr"
    }

    setnvramhex () {
    sudo nvram "$1=$(sed -E 's/(..)/%\1/g' <<< "${2}")"
    }

    setbootvar () {
    @@ -58,53 +80,62 @@ setbootvar () {
    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 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 [[ $theFilePathList =~ $thepat ]]; then
    theFilePathListBytes="$theFilePathList"
    elif [[ -e $theFilePathList ]]; then
    theFilePathListBytes=$(getefipath "$theFilePathList")
    else
    theFilePathListBytes=$(gfxutil "$theFilePathList")
    fi
    local theFilePathListLength=$((${#theFilePathListBytes} / 2))
    local theFilePathListLengthBytes=$(printf "%04x" $theFilePathListLength)
    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 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})"
    setnvramhex "${efiguid}:${thebootvar}" "${thebytes}"
    }

    setbootorder () {
    IFS=''
    local thestring="$*"
    sudo nvram "${efiguid}:BootOrder=$(sed -E "s/[Bb]oot//g;s/(..)(..)/%\2%\1/g" <<< $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)"
    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')
    local BootWhat=""
    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')
    local BootOrder=""
    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
    for theboot in $(<<< "$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
    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"
    @@ -121,7 +152,7 @@ dumpallbootvars () {
    echo "Searching: $thebootvar"
    first=0
    fi
    bootvar $thebootvar 2> /dev/null || break
    bootvar "$thebootvar" 2> /dev/null || break
    ((boot+=inc))
    done
    ((inc < 0)) && ((lowboot = boot))
    @@ -130,6 +161,33 @@ dumpallbootvars () {
    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"
    if ( sudo bless --mount "$thefile" --file "$thefile" --nextonly --setBoot ); then
    local thebootvar=""
    thebootvar=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/Boot\2\1/g')
    local thepath=""
    thepath=$(bootvar -p "$thebootvar" 2> /dev/null)
    local theerr=$?

    if (( theerr == 0 )); then
    echo -n "$thepath"
    else
    echo "# BootNext:$thebootvar not set" 1>&2
    return 1
    fi

    sudo nvram -d $efiguid:BootNext
    sudo nvram -d efi-boot-next-data
    else
    echo '# Bless failed' 1>&2
    return 1
    fi
    return 0
    }

    dumpallioregefipaths () {
    eval "$(
    (ioreg -lw0 -p IODeviceTree; ioreg -lw0) | perl -e '
    @@ -158,22 +216,26 @@ getaaplpathprops () {
    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')"
    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 theproperties=""
    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)
    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})"
    sudo nvram "${thename}=$(sed -E 's/(..)/%\1/g' <<< "${thepart}")"
    elif nvram "${thename}" > /dev/null 2>&1; then
    sudo nvram -d "$thename"
    else
    nvram "${thename}" > /dev/null 2>&1 && sudo nvram -d "$thename" || break
    break
    fi
    ((thevar++))
    done
    @@ -187,7 +249,7 @@ getpanic () {
    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')"
    printf "$(echo -n "$theval" | sed -E '/^'"$thevar"'./s///;s/\\/\\\\/g;s/%/\\x/g')"
    ((i++))
    done
    }
    @@ -216,7 +278,7 @@ testbit () {
    local fname=$5
    if [[ $isset = "printset" ]]; then
    if ((fbit & fbits)); then
    printf $fname
    printf "%s" "$fname"
    if ((!(fbit & fmask))); then
    printf "(error: mask is 0)"
    fi
    @@ -225,32 +287,33 @@ testbit () {
    elif [[ $isset = "printunset" ]]; then
    if ((!(fbit & fbits))); then
    if (((fbit & fmask))); then
    printf "not $fname"
    printf "not %s" "$fname"
    printf "\n"
    fi
    fi
    elif [[ $isset = "printignored" ]]; then
    if ((!(fbit & fmask))); then
    printf "ignore $fname"
    printf "ignore %s" "$fname"
    printf "\n"
    fi
    fi
    }

    binary () {
    local binary=$(echo "obase=2;ibase=10;$(($1+(1<<32)))"|bc)
    printf ${binary:1}
    local binary=""
    binary=$(echo "obase=2;ibase=10;$(($1+(1<<32)))"|bc)
    printf "%s" "${binary:1}"
    }

    parseflags () {
    local fbits=$(($1))
    local fmask=$(($2))
    printf "=========================================================================\n"
    printf "features:%08X %s\n" $fbits $(binary $fbits)
    printf "features:%08X %s\n" $fbits "$(binary $fbits)"
    if [[ -z $2 ]]; then
    fmask=$fbits
    else
    printf " mask:%08X %s\n" $fmask $(binary $fmask)
    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
    @@ -289,15 +352,18 @@ parseflags () {
    }

    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/')
    local ExtendedFirmwareFeatures=""
    ExtendedFirmwareFeatures=$(nvramp 4D1EDE05-38C7-4A6A-9CC6-4BCCA8B38C14:ExtendedFirmwareFeatures 2> /dev/null | xxd -g 8 -e | sed -E '/^[^:]+: +([^ ]+).*/s//0x\1/')
    local ExtendedFirmwareFeaturesMask=""
    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
    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
    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/')
    parseflags "$FirmwareFeatures" "$FirmwareFeaturesMask"
    fi
    }
  12. @joevt joevt revised this gist Dec 31, 2020. 1 changed file with 102 additions and 4 deletions.
    106 changes: 102 additions & 4 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # joevt Dec 14, 2020
    # joevt Dec 30, 2020
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil
    @@ -86,8 +86,10 @@ setdriverorder () {
    }

    dumpallbootvars () {
    local BootNext=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'Boot'\2\1 /g')
    echo "BootNext: $BootNext"
    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
    @@ -102,7 +104,7 @@ dumpallbootvars () {
    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 128:1; echo $((0xFFFF)):-1
    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"
    @@ -203,3 +205,99 @@ getpanic2 () {
    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
    }
  13. @joevt joevt revised this gist Dec 14, 2020. 1 changed file with 11 additions and 6 deletions.
    17 changes: 11 additions & 6 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,5 @@
    # joevt Nov 22, 2020
    # joevt Dec 14, 2020
    # https://forums.macrumors.com/threads/documentation-on-all-parameters-for-nvram.2239034/post-28518123

    gfxutilcmd=~/Downloads/gfxutil

    @@ -85,12 +86,12 @@ setdriverorder () {
    }

    dumpallbootvars () {
    local BootNext=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/'Boot'\2\1 /g')
    local BootNext=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -u -p -c 99999 | sed -E 's/(..)(..)/'Boot'\2\1 /g')
    echo "BootNext: $BootNext"
    echo

    for theType in Boot Driver; do
    local BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/'${theType}'\2\1 /g')
    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
    @@ -101,19 +102,23 @@ dumpallbootvars () {
    IFS=$'\n'
    local lowboot=-1
    for boot in $( {
    eval $(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/echo $((0x\2\1 + 1)):1;echo $((0x\2\1 - 1)):-1;/g'); echo 0:1; echo 128:1; echo $((0xffff)):-1
    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 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)
    thebootvar=${theType}$(printf "%04X" $boot)
    [[ $BootOrder != *"$thebootvar"* ]] || break
    ((boot > lowboot)) || break
    ((inc > 0)) && ((lowboot = boot))
    echo "Searching: $thebootvar"
    if ((first)); then
    echo "Searching: $thebootvar"
    first=0
    fi
    bootvar $thebootvar 2> /dev/null || break
    ((boot+=inc))
    done
  14. @joevt joevt revised this gist Nov 22, 2020. 1 changed file with 6 additions and 2 deletions.
    8 changes: 6 additions & 2 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # joevt Oct 24, 2020
    # joevt Nov 22, 2020

    gfxutilcmd=~/Downloads/gfxutil

    @@ -85,6 +85,10 @@ setdriverorder () {
    }

    dumpallbootvars () {
    local BootNext=$(nvramp $efiguid:BootNext 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/'Boot'\2\1 /g')
    echo "BootNext: $BootNext"
    echo

    for theType in Boot Driver; do
    local BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/'${theType}'\2\1 /g')
    echo "${theType}Order: $BootOrder"
    @@ -193,4 +197,4 @@ getpanic2 () {
    ((i++))
    break
    done
    }
    }
  15. @joevt joevt revised this gist Oct 25, 2020. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # joevt Sep 27, 2020
    # joevt Oct 24, 2020

    gfxutilcmd=~/Downloads/gfxutil

    @@ -86,7 +86,7 @@ setdriverorder () {

    dumpallbootvars () {
    for theType in Boot Driver; do
    local BootOrder=$(nvramp $efiguid:${theType}Order | xxd -p -c 99999 | sed -E 's/(..)(..)/'${theType}'\2\1 /g')
    local BootOrder=$(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/'${theType}'\2\1 /g')
    echo "${theType}Order: $BootOrder"
    IFS=$' '
    for theboot in $(echo $BootOrder); do
    @@ -97,7 +97,7 @@ dumpallbootvars () {
    IFS=$'\n'
    local lowboot=-1
    for boot in $( {
    eval $(nvramp $efiguid:${theType}Order | xxd -p -c 99999 | sed -E 's/(..)(..)/echo $((0x\2\1 + 1)):1;echo $((0x\2\1 - 1)):-1;/g'); echo 0:1; echo 128:1; echo $((0xffff)):-1
    eval $(nvramp $efiguid:${theType}Order 2> /dev/null | xxd -p -c 99999 | sed -E 's/(..)(..)/echo $((0x\2\1 + 1)):1;echo $((0x\2\1 - 1)):-1;/g'); echo 0:1; echo 128:1; echo $((0xffff)):-1
    } | sort -u -t : -k 1n,2n
    ) ; do
    #echo "checking range $boot"
    @@ -193,4 +193,4 @@ getpanic2 () {
    ((i++))
    break
    done
    }
    }
  16. @joevt joevt revised this gist Sep 27, 2020. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    # joevt Sep 26, 2020
    # joevt Sep 27, 2020

    gfxutilcmd=~/Downloads/gfxutil

    @@ -40,7 +40,7 @@ bootvar () {
    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"; echo -n '"'
    echo -n ', "'; gfxutil "$theFilePathList" | cat; echo -n '"'
    }
    [[ -n $theOptionalData ]] && echo -n ", "'"'"$theOptionalDatastring"'"'
    echo
    @@ -126,7 +126,7 @@ dumpallioregefipaths () {
    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; echo/'
    ' | sed -E '/device-properties/d;/(.*) = <(.*)>/s//echo -n "\1 = "; gfxutil \2 | cat; echo/'
    )"
    }

  17. @joevt joevt created this gist Sep 27, 2020.
    196 changes: 196 additions & 0 deletions gfxutil.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,196 @@
    # joevt Sep 26, 2020

    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"; 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 theType in Boot Driver; do
    local BootOrder=$(nvramp $efiguid:${theType}Order | xxd -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 | xxd -p -c 99999 | sed -E 's/(..)(..)/echo $((0x\2\1 + 1)):1;echo $((0x\2\1 - 1)):-1;/g'); echo 0:1; echo 128:1; echo $((0xffff)):-1
    } | sort -u -t : -k 1n,2n
    ) ; do
    #echo "checking range $boot"
    local inc="${boot#*:}"
    local boot=$((${boot%:*}))
    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))
    echo "Searching: $thebootvar"
    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; 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
    }