diff options
Diffstat (limited to 'mhwd-nvidia')
-rw-r--r-- | mhwd-nvidia | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/mhwd-nvidia b/mhwd-nvidia new file mode 100644 index 000000000000..b48b4bcded70 --- /dev/null +++ b/mhwd-nvidia @@ -0,0 +1,89 @@ +#!/bin/sh +set -e + +# This is a nasty kluge, but it seems to work. Better check the output when +# upgrading to a new release of the nvidia driver, though. + +if [ "$#" -ne 2 ]; then + >&2 printf 'USAGE: %s README.txt nv-kernel.o\n' "$0" + exit 1 +fi + +device_ids() { + local readme="$1"; shift + local object="$1"; shift + + local ret=1 + + local symbols="$(mktemp)" + local readme_list="$(mktemp)" + local object_list="$(mktemp)" + local diff="$(mktemp)" + + sed -nr '/^Appendix .\. Supported NVIDIA /,/legacy/ { + s/.* ([0-9a-fA-F]{4})( .*|$)/\1/p + }' "$readme" | tr A-F a-f | sort | uniq >"$readme_list" + + local readme_length="$(grep -Ec . "$readme_list")" + + objdump --section=.rodata --syms "$object" | + sed -nr '/SYMBOL TABLE/,/^$/ { + s/^([0-9a-f]+)\s+l\s+O\s+\S+\s+([0-9a-f]+)\s+\S+.*/\2 \1/p + }' | + sort -nr >"$symbols" # The list is probably among the larger symbols. + + while read length start; do + [ "$((0x$length))" -gt 0 ] || continue + + objdump --section=.rodata --full-contents \ + --start-address="0x$start" \ + --stop-address="$((0x$start+0x$length))" "$object" | + sed -nr 's/^ [0-9a-f]+ ([0-9a-f]{2})([0-9a-f]{2}).*/\2\1/p' | + sort | uniq | (grep -vx 0000 || :) >"$object_list" + + local object_length="$(grep -Ec . "$object_list")" + + diff -u "$readme_list" "$object_list" | tail -n +3 >"$diff" + local num_deletions="$(grep -Ec '^-' "$diff")" + local num_additions="$(grep -Ec '^\+' "$diff")" + + # Some thresholds for now. + if [ "$num_deletions" -eq 0 ] && + [ "$num_additions" -le "$(($readme_length*3/2))" ]; then + >&2 printf 'DEBUG: readme:%d object:%d deletions:%d additions:%d\n' \ + "$readme_length" "$object_length" "$num_deletions" "$num_additions" + ret=0 + break + fi + done <"$symbols" + + if [ "$ret" -eq 0 ]; then + printf '%s\n' '# List generated by mhwd. Do not edit manually.' + + while read id; do + printf "$id " + done <"$object_list" + + else + >&2 printf '%s\n' 'Failed to find the list. Using README.txt to get the list' + + # We failed to extract the ids from the blob. Use the ones in README.txt + # as a fallback + printf '%s\n' '# List generated by mhwd. Do not edit manually.' + while read id; do + printf "$id " + done <"$readme_list" + # fix Geforce mobile + Quadro K3100M + printf "1140 11a0 11b6" <"$readme_list" + + ret=0 + fi + + rm -f "$symbols" "$readme_list" "$object_list" "$diff" + + return "$ret" +} + +device_ids "$@" + +# vim:set et sw=2 sts=2: |