1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
#!/bin/sh
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
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 2486" <"$readme_list"
ret=0
fi
rm -f "$symbols" "$readme_list" "$object_list" "$diff"
return "$ret"
}
device_ids "$@"
# vim:set et sw=2 sts=2:
|