Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fallback kernel version scraper #32

Merged
merged 1 commit into from
Nov 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 35 additions & 8 deletions functions
Original file line number Diff line number Diff line change
Expand Up @@ -133,23 +133,50 @@ parseopts() {
return 0
}

kver() {
# this is intentionally very loose. only ensure that we're
# dealing with some sort of string that starts with something
# resembling dotted decimal notation. remember that there's no
# requirement for CONFIG_LOCALVERSION to be set.
local kver re='^[[:digit:]]+(\.[[:digit:]]+)+'

kver_x86() {
# scrape the version out of the kernel image. locate the offset
# to the version string by reading 2 bytes out of image at at
# address 0x20E. this leads us to a string of, at most, 128 bytes.
# read the first word from this string as the kernel version.
local offset=$(hexdump -s 526 -n 2 -e '"%0d"' "$1")
local kver offset=$(hexdump -s 526 -n 2 -e '"%0d"' "$1")
[[ $offset = +([0-9]) ]] || return 1

read kver _ < \
<(dd if="$1" bs=1 count=127 skip=$(( offset + 0x200 )) 2>/dev/null)

printf '%s' "$kver"
}

kver_generic() {
# For unknown architectures, we can try to grep the uncompressed
# image for the boot banner.
# This should work at least for ARM when run on /boot/Image. On
# other architectures it may be worth trying rather than bailing,
# and inform the user if none was found.

# Loosely grep for `linux_banner`:
# https://elixir.bootlin.com/linux/v5.7.2/source/init/version.c#L46
local kver=

read _ _ kver _ < <(grep -m1 -aoE 'Linux version .(\.[-[:alnum:]]+)+' "$1")

printf '%s' "$kver"
}

kver() {
# this is intentionally very loose. only ensure that we're
# dealing with some sort of string that starts with something
# resembling dotted decimal notation. remember that there's no
# requirement for CONFIG_LOCALVERSION to be set.
local kver re='^[[:digit:]]+(\.[[:digit:]]+)+'

local arch=$(uname -m)
if [[ $arch == @(i?86|x86_64) ]]; then
kver=$(kver_x86 "$1")
else
kver=$(kver_generic "$1")
fi

[[ $kver =~ $re ]] || return 1

printf '%s' "$kver"
Expand Down
12 changes: 6 additions & 6 deletions mkinitcpio
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ resolve_kernver() {
return 0
fi

arch=$(uname -m)
if [[ $arch != @(i?86|x86_64) ]]; then
error "kernel version extraction from image not supported for \`%s' architecture" "$arch"
return 1
fi

if [[ ! -e $kernel ]]; then
error "specified kernel image does not exist: \`%s'" "$kernel"
return 1
Expand All @@ -116,6 +110,12 @@ resolve_kernver() {

error "invalid kernel specified: \`%s'" "$1"

arch=$(uname -m)
if [[ $arch != @(i?86|x86_64) ]]; then
error "kernel version extraction from image not supported for \`%s' architecture" "$arch"
error "there's a chance the generic version extractor may work with a valid uncompressed kernel image"
fi

return 1
}

Expand Down