Compare commits

..

No commits in common. "rawhide" and "f36" have entirely different histories.

13 changed files with 90 additions and 492 deletions

View file

@ -1,79 +1,3 @@
# kernel-srpm-macros
The kernel-srpm-macros package
This source package results in two "binary" packages, kernel-rpm-macros
and kernel-srpm-macros. The role and locations of files is as follows:
kernel-srpm-macros:
/usr/lib/rpm/fileattrs/kmod.attr
For /lib/modules/XYZ/modules.builtin and .../MODULE.ko.XYZ
specifies a Lua script to generate kmod(MODULE.ko)
"Provides:" deps
/usr/lib/rpm/macros.d/macros.kernel-srpm
Automatically included by all rpm invocations.
Defines %kernel_arches (try rpm --eval '%kernel_arches')
Question: what uses this macro? I didn't find any users.
kernel-rpm-macros:
/usr/lib/rpm/redhat/find-provides.ksyms
Runs from rpmbuild at the end of kernel builds and 3rd party module
builds, to extract
kernel(SYMBOL)=0xHASH "Provides:" deps from modules in kernel packages,
and ksym(SYMBOL)=0xHASH for 3rd party modules.
Takes input list of files on stdin.
/usr/lib/rpm/fileattrs/provided_ksyms.attr
For newer rpmbuild with "internal dependency generators",
this file specifies that find-provides.ksyms should be run
only on .ko.XYZ files
(with "external dependency generators", the script needs to
filter out the files by itself).
/usr/lib/rpm/redhat/find-requires.ksyms
?
/usr/lib/rpm/fileattrs/required_ksyms.attr
For newer rpmbuild with "internal dependency generators",
this file specifies that find-requires.ksyms should be run
only on .ko.XYZ files, and not for /lib/modules/XYZ/kernel/*
(IOW: only for building 3rd-party modules)
/usr/lib/rpm/redhat/find-provides.d/modalias.prov
Runs from rpmbuild at the end of kernel builds and 3rd party module
builds, to extract
modalias(pci:SOMETHING)=OPTIONALLY_VERSION "Provides:" deps from modules
in kernel and 3rd party modules packages.
Takes input list of files on stdin.
Question: what uses these deps?
/usr/lib/rpm/fileattrs/modalias.attr
For newer rpmbuild with "internal dependency generators",
this file specifies that modalias.prov should be run
only on .ko.XYZ files
/usr/lib/rpm/redhat/find-provides.d/firmware.prov
?
/usr/lib/rpm/kabi.sh
Runs from rpmbuild at the end of kernel build to extract
kernel(SYMBOL)=0xHASH "Provides:" deps.
/usr/lib/rpm/fileattrs/kabi.attr
For newer rpmbuild with "internal dependency generators",
this file specifies that kabi.sh should be run on
/boot/symvers-* and /lib/modules/XYZ/symvers.gz
/usr/lib/rpm/macros.d/macros.kmp
Automatically included by all rpm invocations.
Defines a number of macros.
/usr/lib/rpm/redhat/brp-kmod-restore-perms
?
/usr/lib/rpm/redhat/brp-kmod-set-exec-bit
?
/usr/lib/rpm/redhat/kmodtool
?
/usr/lib/rpm/redhat/rpmsort
?
/usr/lib/rpm/redhat/symset-table
?
The kernel-srpm-macros package

View file

@ -1,16 +1,12 @@
#! /bin/bash
IFS=$'\n'
export LC_ALL=C
# Prevent elfutils from trying to download debuginfos
unset DEBUGINFOD_URLS
for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
dep_pfx="ksym"
# For built-in kmods, "kernel()" syntax is used instead of "ksym()"
printf "%s" "$module" | grep -v "^${RPM_BUILD_ROOT}/\?lib/modules/[1-9][^/]*/kernel" > /dev/null \
|| dep_pfx="kernel"
|| dep_pfx="kernel"
tmpfile=""
if [ "x${module%.ko}" = "x${module}" ]; then
@ -37,102 +33,24 @@ for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
module="$tmpfile"
fi
# A modversion can be stored as an ELF symbol in various ways:
# - An immediate symbol whose value is available directly; it shows up
# in the nm or objdump -t output, for example:
# $ nm mlx5_core_5.14.x86_64.ko | grep '__crc_' | head -n 3
# 0000000092f175ca A __crc_mlx5_access_reg
# 000000005b88c9f1 A __crc_mlx5_add_flow_rules
# 00000000e7c0ec8a A __crc_mlx5_alloc_bfreg
# $ objdump -t lib/modules/mlx5_core_5.14.x86_64.ko | grep __crc_ | sort -k 5,5 | head -n 3
# 0000000092f175ca g *ABS* 0000000000000000 __crc_mlx5_access_reg
# 000000005b88c9f1 g *ABS* 0000000000000000 __crc_mlx5_add_flow_rules
# 00000000e7c0ec8a g *ABS* 0000000000000000 __crc_mlx5_alloc_bfreg
# $ zgrep mlx5_access_reg ./lib/modules/5.14.0-284.15.1.el9_2.x86_64/symvers.gz
# 0x92f175ca mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL
# This approach was being used on x86 and arm before Linux 5.19,
# for example.
#
# - A globally or locally visible symbol in a read-only (or not;
# sometimes .rodata is not a read-only section, after all, as binutils
# commit binutils-2_33~1385 has revealed (and binutils-2_35~1768 hasn't
# concealed back)) section (historically .rodata, __kcrctab/__kcrctab_gpl
# since Linux v5.19-rc1~139^2~2):
# $ nm mlx5_core_5.14.s390x.ko | grep '__crc_' | head -n 3
# 0000000000002f7c R __crc_mlx5_access_reg
# 0000000000003304 R __crc_mlx5_add_flow_rules
# 0000000000002d2c R __crc_mlx5_alloc_bfreg
# This layout is used on ppc since Linux v4.10-rc7~15^2~1, for example,
# and on all architectures since Linux 5.19. To extract the symbol
# versions in this case, we get the offset and the section name
# from the "objdump -t" output:
# $ objdump -t lib/modules/mlx5_core_5.14.s390x.ko | grep '__crc_' | sort -k 5,5 | head -n 2
# 0000000000002f7c g .rodata 0000000000000000 __crc_mlx5_access_reg
# 0000000000003304 g .rodata 0000000000000000 __crc_mlx5_add_flow_rules
# and the section contents from the "readelf -R" call:
# $ readelf -R .rodata mlx5_core_5.14.s390x.ko
# [... skipped output ...]
# 0x00002f70 6c6f635f 6e6f6465 00000000 ed6560a8 loc_node.....e`.
# ^^^^^^^^
# comparison with the contents
# of lib/modules/5.14.0-284.15.1.el9_2.s390x/symvers.gz corroborates
# its correctness:
# 0xed6560a8 mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL
# As mentioned earlier, for the later kernel versions, __kcrctab{,_gpl}
# sections are used:
# $ objdump -t lib/modules/mlx5_core_6.4.x86_64.ko | grep '__crc_' | sort -k 5,5 | head -n 2
# 0000000000000000 l __kcrctab_gpl 0000000000000000 __crc_mlx5_access_reg
# 0000000000000090 l __kcrctab 0000000000000000 __crc_mlx5_add_flow_rules
# $ readelf -R __kcrctab_gpl mlx5_core_6.4.x86_64.ko
# 0x00000000 38b0d3c3 1840ce35 b99babc7 70b4700c 8....@.5....p.p.
# ^^^^^^^^
# and in lib/modules/6.4.0-0.rc1.20230511git80e62bc8487b.19.eln126.x86_64/symvers.xz
# we see that it is correct (when accounted for the little endianness):
# 0xc3d3b038 mlx5_access_reg drivers/net/ethernet/mellanox/mlx5/core/mlx5_core EXPORT_SYMBOL_GPL
# This data, after some post-processing, can be used in the awk script
# that extracts parts of the section according to the offsets got
# from the "objdump -t" output.
objdump -t "$module" \
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
--non-decimal-data \
'BEGIN { revbytes = 0 }
function check_endianness( t) {
if (revbytes) return revbytes;
revbytes = -1;
while (("readelf -h \"" module "\"" | getline t) > 0) {
if (match(t, /^ Data: *2\047s complement, little endian$/)) {
revbytes = 1;
break;
}
}
return revbytes;
}
function readsect(name, a, t) {
a = "";
while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
if (check_endianness() == 1)
a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a);
sectdata[name] = a;
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) {
if (a[2] == "*ABS*") {
printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1]));
} else {
if (!(a[2] in sectdata)) { readsect(a[2]) }
printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8))
}
}'
if [[ -n $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then
nm $module \
| sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \
| awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08x\n", $2, $1)}' \
| LC_ALL=C sort -u
else
ELFRODATA=$(readelf -R .rodata $module | awk '/0x/{printf $2$3$4$5}')
if [[ -n $(readelf -h $module | grep "little endian") ]]; then
RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g')
else
RODATA=$ELFRODATA
fi
for sym in $(nm $module | sed -r -ne 's:^0*([0-9a-f]+) R __crc_(.+):0x\1 \2:p'); do
echo $sym $RODATA
done \
| awk --non-decimal-data '{printf("'"${dep_pfx}"'(%s) = 0x%08s\n", $2, substr($3,($1*2)+1,8))}' \
| LC_ALL=C sort -u
fi
[ -z "$tmpfile" ] || rm -f -- "$tmpfile"
done \
| sort -k1,1 -u
done

View file

@ -6,10 +6,6 @@
# provided by an external module and "ksym" replaces th regular "kernel" dep.
IFS=$'\n'
export LC_ALL=C
# Prevent elfutils from trying to download debuginfos
unset DEBUGINFOD_URLS
# Extract all of the symbols provided by this module.
all_provides() {
@ -39,49 +35,26 @@ all_provides() {
module="$tmpfile"
fi
objdump -t "$module" \
| awk \
-v 'dep_pfx='"$dep_pfx" \
-v 'module='"$module" \
--non-decimal-data \
'BEGIN { revbytes = 0 }
function check_endianness( t) {
if (revbytes) return revbytes;
revbytes = -1;
while (("readelf -h \"" module "\"" | getline t) > 0) {
if (match(t, /^ Data: *2\047s complement, little endian$/)) {
revbytes = 1;
break;
}
}
return revbytes;
}
function readsect(name, a, t) {
a = "";
while (("readelf -R \"" name "\" \"" module "\"" | getline t) > 0) {
if (match(t, /^ 0x[0-9a-f]{8}/))
a = a substr(t, 14, 8) substr(t, 23, 8) substr(t, 32, 8) substr(t, 41, 8);
}
if (revbytes) { a = gensub(/(..)(..)(..)(..)/, "\\4\\3\\2\\1", "g", a); }
sectdata[name] = a;
}
match($0, /^([0-9a-f]+) [gl]...... (.*) [0-9a-f]+ __crc_(.*)$/, a) {
if (a[2] == "*ABS*") {
printf("%s(%s) = 0x%08x\n", dep_pfx, a[3], strtonum("0x" a[1]));
} else {
if (!(a[2] in sectdata)) { readsect(a[2]) }
printf("%s(%s) = 0x%08s\n", dep_pfx, a[3], substr(sectdata[a[2]], (strtonum("0x" a[1]) * 2) + 1, 8))
}
}'
if [[ -n $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p') ]]; then
nm "$module" \
| sed -r -ne 's:^0*([0-9a-f]+) A __crc_(.+):0x\1 \2:p' \
| awk --non-decimal-data '{printf("%s:0x%08x\n", $2, $1)}'
else
ELFRODATA=$(readelf -R .rodata "$module" | awk '/0x/{printf $2$3$4$5}')
if [[ -n $(readelf -h "$module" | grep "little endian") ]]; then
RODATA=$(echo $ELFRODATA | sed 's/\(..\)\(..\)\(..\)\(..\)/\4\3\2\1/g')
else
RODATA=$ELFRODATA
fi
for sym in $(nm "$module" | sed -r -ne 's:^0*([0-9a-f]+) R __crc_(.+):0x\1 \2:p'); do
echo $sym $RODATA
done \
| awk --non-decimal-data '{printf("%s:0x%08s\n", $2, substr($3,($1*2)+1,8))}'
fi
[ -z "$tmpfile" ] || rm -f -- "$tmpfile"
done \
| sort -k1,1 -u
| LC_ALL=C sort -k1,1 -u
}
# Extract all of the requirements of this module.
@ -94,15 +67,15 @@ all_requires() {
{printf("%s:0x%08x\n", $2, $1)}' \
| sed -r -e 's:$:\t'"$1"':'
done \
| sort -k1,1 -u
| LC_ALL=C sort -k1,1 -u
}
# Filter out requirements fulfilled by the module itself.
mod_requires() {
join -t $'\t' -j 1 -v 1 \
LC_ALL=C join -t $'\t' -j 1 -v 1 \
<(all_requires "$@") \
<(all_provides "$@") \
| sort -k1,1 -u
| LC_ALL=C sort -k1,1 -u
}
if ! [ -e /sbin/modinfo -a -e /sbin/modprobe ]; then
@ -165,23 +138,23 @@ if [ ${#modules[@]} -gt 0 ]; then
{ print $2 ":" $1 }
' \
| sed -r -e 's:$:\t'"$kernel"':' \
| sort -k1,1 -u > $symvers
| LC_ALL=C sort -k1,1 -u > $symvers
# Symbols matching with the kernel get a "kernel" dependency
mod_req=$(mktemp -t mod_req.XXXXX)
mod_requires "${modules[@]}" > "$mod_req"
join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \
LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
| awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "kernel(" $1 ") = " $2 }'
# Symbols from elsewhere get a "ksym" dependency
join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | sort -u \
LC_ALL=C join -t $'\t' -j 1 -v 2 $symvers "$mod_req" | LC_ALL=C sort -u \
| awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print "ksym(" $1 ") = " $2 }'
os_id=$(sed -nr '/^ID[[:space:]]*=/{ s/ID[[:space:]]*=[[:space:]]*//; s/^"(.*)"$/\1/; p }' /etc/os-release)
if [ "rhel" = "$os_id" ]; then
# Check kABI if the kabi-stablelists package is installed
# Do this last so we can try to output this error at the end
kabi_check_symbols=($(join -t $'\t' -j 1 $symvers "$mod_req" | sort -u \
kabi_check_symbols=($(LC_ALL=C join -t $'\t' -j 1 $symvers "$mod_req" | LC_ALL=C sort -u \
| awk 'BEGIN { FS = "[\t:]" ; OFS = "\t" } { print $1 }'))
check_kabi "${kabi_check_symbols[@]}"
fi

View file

@ -1,2 +1,2 @@
%__kabi_provides %{_rpmconfigdir}/kabi.sh
%__kabi_path ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)$
%__kabi_path ^(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz$

10
kabi.sh
View file

@ -7,16 +7,10 @@
IFS=$'\n'
for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.(gz|xz)') "$@";
for symvers in $(grep -E '(/boot/symvers-.*|/lib/modules/[1-9].*/symvers)\.gz') "$@";
do
cat_prog="cat"
case "$symvers" in
*.gz) cat_prog="zcat" ;;
*.xz) cat_prog="xzcat" ;;
esac
# We generate dependencies only for symbols exported by vmlinux itself
# and not for kmods here as they are spread across subpackages,
# so Provides: generation for kmods is handled by find-provides.ksyms.
"$cat_prog" "$symvers" | awk '/[^ ]* [^ ]* vmlinux .*/ { print "kernel(" $2 ") = " $1 }'
zcat $symvers | awk '/[^ ]* [^ ]* vmlinux .*/ { print "kernel(" $2 ") = " $1 }'
done

View file

@ -1,7 +1,7 @@
Name: kernel-srpm-macros
Version: 1.0
# when bumping version and resetting release, don't forget to bump version of kernel-rpm-macros as well
Release: 27%{?dist}
Release: 14%{?dist}
Summary: RPM macros that list arches the full kernel is built on
# This package only exist in Fedora repositories
# The license is the standard (MIT) specified in
@ -56,25 +56,10 @@ The variable to use is kernel_arches.
%package -n kernel-rpm-macros
Version: 205
Summary: Macros and scripts for building kernel module packages
# rpmsort is GPL-2.0-or-later
License: MIT AND GPL-2.0-or-later
Requires: redhat-rpm-config >= 205
# for brp-kmod-compress
Requires: %{_bindir}/xz
# for brp-kmod-compress, brp-kmod-set-exec-bit
# for brp-kmod-set-exec-bit
Requires: %{_bindir}/find
# for find-provides.ksyms, find-requires.ksyms, kmodtool
Requires: %{_bindir}/sed
# for find-provides.ksyms, find-requires.ksyms
Requires: %{_bindir}/awk
Requires: %{_bindir}/grep
Requires: %{_bindir}/nm
Requires: %{_bindir}/objdump
Requires: %{_bindir}/readelf
# for find-requires.ksyms
Requires: %{_sbindir}/modinfo
Requires: %{_sbindir}/modprobe
%description -n kernel-rpm-macros
Macros and scripts for building kernel module packages.
@ -94,7 +79,7 @@ cp -p %{sources} .
mkdir -p %{buildroot}/%{_rpmconfigdir}/macros.d
install -p -m 0644 -t %{buildroot}/%{_rpmconfigdir}/macros.d macros.kernel-srpm
%if 0%{?rhel} >= 8
sed -i 's/^%%kernel_arches.*/%%kernel_arches x86_64 s390x ppc64le aarch64 riscv64/' \
sed -i 's/^%%kernel_arches.*/%%kernel_arches x86_64 s390x ppc64le aarch64/' \
%{buildroot}/%{_rpmconfigdir}/macros.d/macros.kernel-srpm
%endif
@ -136,56 +121,6 @@ install -p -m 644 -t "%{buildroot}%{_fileattrsdir}" modalias.attr
%{rrcdir}/rpmsort
%changelog
* Thu Jul 24 2025 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-27
- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
* Tue Apr 01 2025 Andrea Bolognani <abologna@redhat.com> - 1.0-26
- Finish adding riscv64 (thanks Zhengyu He)
* Fri Jan 17 2025 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-25
- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
* Thu Jul 18 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-24
- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
* Wed Mar 06 2024 David Abdurachmanov <davidlt@rivosinc.com> - 1.0-23
- Add riscv64
* Wed Jan 24 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-22
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-21
- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-20
- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
* Tue May 09 2023 Eugene Syromiatnikov <esyr@redhat.com> - 1.0-19
- Capture local __crc_* symbols for "Provides: kernel()".
- Add support for XZ compression for the symvers file.
- Fix "Provides: kernel()" generation when both __kcrctab and __kcrctab_gpl
are present.
- Fix regression for "Provides:" generation in cases when modversions are stored
in a section that is over 64K in size.
- Speedup and cleanup changes in find-provides.ksyms and find-requires.ksyms.
- Fix regex usage in kmod.attr. (Denys Vlasenko)
- Implement modalias "Provides:" grouping. (Denys Vlasenko)
- Speedup and cleanup changes in modalias.prov and kmod.attr. (Denys Vlasenko)
* Tue Mar 30 2023 Eugene Syromiatnikov <esyr@redhat.com> - 1.0-18
- Avoid triggering debuginfod during elfutils tools usage.
* Tue Jan 31 2023 Eugene Syromiatnikov <esyr@redhat.com> - 1.0-17
- Support storing of __crc_* symbols in sections other than .rodata.
- Work around a change in type of __crc_* symbols for some kmods printed by nm
on ppc64le and s390x.
* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-16
- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
* Thu Jul 21 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-15
- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 1.0-14
- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild

View file

@ -1,54 +1,31 @@
%__kmod_path ^/lib/modules/.*/(modules.builtin|.*\.ko|.*\.ko\.gz|.*\.ko\.bz2|.*\.ko\.xz|.*\.ko\.zst)$
# Notes on Lua:
# The backslash in strings (like "\n" newline) needs to be doubled
# because we are inside rpm macro. Single backslashes before most chars
# disappear (removed by rpm's parser), so "\n" turns into just "n".
# In string.gsub patterns, unlike regexps, backslash has no special meaning.
# It can't escape . and such. (Use one-character set [.] to represent
# literal period, or lua's percent escape: %.)
# Pipe (|) has no special meaning too.
%__kmod_provides() %{lua:
function basename(fn)
local b = string.gsub(fn, ".*/", "")
-- the above adjusts gsub() result to 1 value
-- "return f()" construct would return _all_ values, two in case of gsub()
return b
return string.gsub(fn, "(.*/)(.*)", "%2")
end
function strip_compress_sfx(fn)
local cnt
fn, cnt = string.gsub(fn, "%.gz$", "")
if cnt == 1 then return fn; end
fn, cnt = string.gsub(fn, "%.bz2$", "")
if cnt == 1 then return fn; end
fn, cnt = string.gsub(fn, "%.xz$", "")
if cnt == 1 then return fn; end
fn, cnt = string.gsub(fn, "%.zst$", "")
return fn
return string.gsub(fn, "(.*)(\.gz|\.bz2|\.xz|\.zst)?$", "%1")
end
function printdep(mod)
print("kmod("..mod..") ")
end
local fn = rpm.expand("%1")
local fn = rpm.expand("%{1}")
local bn = basename(fn)
if bn == "modules.builtin" then
for l in io.lines(fn) do
local builtin_mod = basename(l)
printdep(builtin_mod)
local nocompr = strip_compress_sfx(builtin_mod)
if nocompr ~= builtin_mod then
printdep(nocompr)
if strip_compress_sfx(builtin_mod) ~= builtin_mod then
printdep(strip_compress_sfx(builtin_mod))
end
end
else
local mod = string.match(bn, "%g+%.ko")
local mod = string.match(bn, "%g+.ko")
if mod then
printdep(mod)
local nocompr = strip_compress_sfx(mod)
if nocompr ~= mod then
printdep(nocompr)
end
printdep(mod)
if strip_compress_sfx(mod) ~= mod then
printdep(strip_compress_sfx(mod))
end
end
end
}

View file

@ -1,3 +1,3 @@
# kernel_arches lists what arches the full kernel is built for.
%kernel_arches x86_64 s390x ppc64le aarch64 %{arm} riscv64
%kernel_arches x86_64 s390x ppc64le aarch64 %{arm}

View file

@ -59,7 +59,7 @@ redhat_kmp_has_post_hooks 1
%global kmodtool %{-s*}%{!-s:/usr/lib/rpm/redhat/kmodtool} \
%global kmod_version %{-v*}%{!-v:%{version}} \
%global kmod_release %{-r*}%{!-r:%{release}} \
%global latest_kernel %({ rpm -q --qf '%%{VERSION}-%%{RELEASE}.%%{ARCH}\\\\n' kernel-rt-devel kernel-aarch64-devel kernel-devel | grep -v 'is not installed' | /usr/lib/rpm/redhat/rpmsort -r | head -n 1; echo '%%%%{nil}'; } | head -n 1) \
%global latest_kernel %({ rpm -q --qf '%%{VERSION}-%%{RELEASE}.%%{ARCH}\\\\n' `rpm -qa | egrep "^kernel(-rt|-aarch64)?-devel" | /usr/lib/rpm/redhat/rpmsort -r | head -n 1`; echo '%%%%{nil}'; } | head -n 1) \
%{!?kernel_version:%{expand:%%global kernel_version %{latest_kernel}}} \
%global kverrel %(%{kmodtool} verrel %{?kernel_version} 2>/dev/null) \
flavors="default" \

104
modalias.prov Executable file → Normal file
View file

@ -26,15 +26,13 @@ if ! [ -z "$is_kernel_package" ]; then
exit 0
fi
# Check for presence of the commands used.
# "command" is a builtin, faster to use than fork+execing "which" - see
# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html
command -v /sbin/modinfo >/dev/null || exit 1
command -v sed >/dev/null || exit 1
command -v sort >/dev/null || exit 1
# Check for presence of the commands used
which /sbin/modinfo >/dev/null || exit 0
which sed >/dev/null || exit 0
which sort >/dev/null || exit 0
print_modaliases() {
local class="$1" variants="$2" pos="$3"
declare class=$1 variants=$2 pos=$3
if [ -n "$variants" ]; then
echo "${class:0:pos}[$variants]${class:pos+1}"
else
@ -42,87 +40,39 @@ print_modaliases() {
fi
}
# Try to make "provides" list a bit smaller:
# find "mergeable" strings a-la
# modalias(pci:v0000168Cd00000023sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000024sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000027sv*sd*bc*sc*i*)
# modalias(pci:v0000168Cd00000029sv*sd*bc*sc*i*)
# replace with
# modalias(pci:v0000168Cd0000002[3479]sv*sd*bc*sc*i*)
combine_modaliases() {
local unused_len next prev variants="" pos="" n end xc
# Due to set -e, we can exit with exitcode 1 on read EOF
# and this makes our caller think we failed. "|| return 0" prevents this:
IFS=' ' read unused_len prev || return 0
# For each line after the first...
while IFS=' ' read unused_len next; do
if [ -z "$pos" ]; then
# 2nd line: after "modalias(" prefix, for each char in prev line...
n=9
end=${#prev}
# TODO speedup? if [ $end != ${#next} ]; then line is not mergeable
else
# 3rd+ lines: only check the char at the same position
n=$pos
end=$((pos + 1))
fi
# Search for aaaNbbb,aaaMbbb line pair, where N and M chars differ.
# sort -u guarantees there are no identical line pairs.
# We assume that lines will not differ only in " = version" suffix.
for ((; n < $end; n++)); do
if [ "${prev:0:n}" != "${next:0:n}" ]; then
# the prefixes already aren't the same: break
n=$end
declare tag class variants="" pos="" n
read class
while read tag; do
for ((n=0; n<${#class}; n++)); do
if [ "*" != "${class:n:1}" -a \
"${class:0:n}" = "${tag:0:n}" -a \
"${class:n+1}" = "${tag:n+1}" ] &&
( [ -z "$pos" ] || [ $n = $pos ] ); then
variants="${variants:-${class:n:1}}${tag:n:1}"
pos=$n
break
fi
# If suffixes differ, go to next char
[ x"${prev:n+1}" != x"${next:n+1}" ] && continue
# Found aaaNbbb,aaaMbbb. If N and M aren't special...
xc=x"${prev:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
xc=x"${next:n:1}"
[ x"[" = "$xc" -o x"]" = "$xc" ] && continue
[ x"?" = "$xc" -o x"*" = "$xc" ] && continue
# Add M (and maybe N) to $variants, go to next line
variants="${variants:-${prev:n:1}}${next:n:1}"
pos=$n
break
done
if [ $n -eq $end ]; then
# This line is not mergeable with the previous one(s),
# print collected merged line and reset the state
print_modaliases "$prev" "$variants" "$pos"
variants=""
pos=""
prev=$next
if [ $n -eq ${#class} ]; then
print_modaliases "$class" "$variants" "$pos"
variants=
pos=
class=$tag
fi
done
# Print last collected merged line
print_modaliases "$prev" "$variants" "$pos"
print_modaliases "$class" "$variants" "$pos"
}
for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
modver=$(/sbin/modinfo -F version "$module")
# delete possible extra lines because some modules have *two* version tags. *cough*b44*cough*
modver=${modver%%$'\n'*} # using $'' bashism, avoid running "head -n1" process
# replace any strange chars with underscores.
# [!...] is glob's "match any char not in set" pattern
# (although bash supports [^...] too, it is not standard)
modver=${modver//[!0-9a-zA-Z._]/_}
# only add version tag if it indeed has a version
# | head -n1 because some modules have *two* version tags. *cough*b44*cough*
modver=$(/sbin/modinfo -F version "$module"| head -n1)
modver=${modver//[^0-9a-zA-Z._]/_}
# only add version tag if it has a version
[ -z "$modver" ] || modver=" = $modver"
/sbin/modinfo -F alias "$module" \
| sed -E "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,"
# Below: combining code can only possibly combine lines of equal length.
# Prepend line lengths before sort, so that same-length lines end up next
# to each other. (The lengths are discarded by combine_modaliases).
| sed -nre "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,p"
done \
| { while read line; do echo "${#line} $line"; done } \
| LC_ALL=C sort -u \
| sort -u \
| combine_modaliases

View file

@ -1,31 +0,0 @@
#! /bin/bash -efu
# This fetches test data from current system's /lib/modules
# to /tmp/COLLECT
IFS=$'\n'
find /lib/modules | grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$' \
| while IFS='' read -r module; do
modver=$(/sbin/modinfo -F version "$module")
# delete possible extra lines because some modules have *two* version tags. *cough*b44*cough*
modver=${modver%%$'\n'*} # using $'' bashism, avoid running "head -n1" process
# replace any strange chars with underscores.
# [!...] is glob's "match any char not in set" pattern
# (although bash supports [^...] too, it is not standard)
modver=${modver//[!0-9a-zA-Z._]/_}
# only add version tag if it has a version
[ -z "$modver" ] || modver=" = $modver"
d="/tmp/COLLECT$module"
d="${d%/*}"
mkdir -p "$d"
out=`/sbin/modinfo -F alias "$module" \
| sed -E "s,[^][0-9a-zA-Z._:*?/-],_,g; s,(.+),modalias(\\1)$modver,"`
[ "$out" ] || continue
echo "/tmp/COLLECT$module.modalias$modver" >&2
printf '%s\n' "$out" >"/tmp/COLLECT$module.modalias"
done

View file

@ -1,42 +0,0 @@
#!/bin/sh
function die()
{
printf '%s\n' "$*" >&2
exit 1
}
set -e
cd modalias.prov.testdata
test -x ../../modalias.prov || die "No ../../modalias.prov"
# Copy and add -t option to modalias.prov
cp ../../modalias.prov modalias.prov
patch -p1 <<"EOF"
--- a/modalias.prov
+++ b/modalias.prov
@@ -105,6 +105,17 @@ combine_modaliases() {
print_modaliases "$prev" "$variants" "$pos"
}
+if [ "$#" = 2 ] && [ "$1" = "-t" ]; then
+ cat -- "$2" \
+ | { while read line; do echo "${#line} $line"; done } \
+ | LC_ALL=C sort -u \
+ | combine_modaliases \
+ >"$2.test"
+ echo "Comparing results for $2"
+ diff -u "$2.right" "$2.test" && rm -- "$2.test"
+ exit
+fi
+
for module in $(grep -E '/lib/modules/.+\.ko(\.gz|\.bz2|\.xz|\.zst)?$') "$@"; do
modver=$(/sbin/modinfo -F version "$module")
# delete possible extra lines because some modules have *two* version tags. *cough*b44*cough*
EOF
find | grep '\.ko.*\.modalias$' | xargs -n1 ./modalias.prov -t
# Rename newly generated .test as .right
#find | grep '\.ko.*\.modalias$' | xargs -I'{}' mv '{}'.test '{}'.right

Binary file not shown.