respeaker / seeed-voicecard

2 Mic Hat, 4 Mic Array, 6-Mic Circular Array Kit, and 4-Mic Linear Array Kit for Raspberry Pi
GNU General Public License v3.0
470 stars 284 forks source link

Fix get_kernel_version() to get dpkg to look for the right headers #336

Closed GuillaumeRossolini closed 1 year ago

GuillaumeRossolini commented 1 year ago

The following is using HinTak's repository on the v6.1 branch, on a Raspberry Pi Zero W with the Raspberry Pi OS Lite (32-bit) image.

$ uname -r
6.1.21+

Executing ./install.sh on a raspberry zero w, recently reimaged, with barely anything installed on top of the default image (certainly nothing kernel-related), results in errors along these lines:

sudo ./install.sh
Hit:1 http://raspbian.raspberrypi.org/raspbian bullseye InRelease
Hit:2 http://archive.raspberrypi.org/debian bullseye InRelease
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
4 packages can be upgraded. Run 'apt list --upgradable' to see them.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
raspberrypi-kernel is already the newest version (1:1.20230405-1).
raspberrypi-kernel-headers is already the newest version (1:1.20230405-1).
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package linux-raspi
E: Unable to locate package linux-headers-raspi
E: Unable to locate package linux-image-raspi
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
dkms is already the newest version (2.8.4-3).
git is already the newest version (1:2.30.2-1+deb11u2).
i2c-tools is already the newest version (4.2-1+b1).
libasound2-plugins is already the newest version (1.2.2-2).
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.
dpkg-query: package 'linux-headers-' is not installed
dpkg-query: package '6.1.21+' is not installed
Use dpkg --contents (= dpkg-deb --contents) to list archive files contents.
 !!! Your kernel version is

6.1.21+
     Not found *** corresponding *** kernel headers with apt-get.
     This may occur if you have ran 'rpi-update'.
 Choose  *** y *** will revert the kernel to version  then continue.
 Choose  *** N *** will exit without this driver support, by default.
Would you like to proceed? (y/N)
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 4 not upgraded.
Need to get 0 B/102 MB of archives.
After this operation, 0 B of additional disk space will be used.
(Reading database ... 101414 files and directories currently installed.)
Preparing to unpack .../raspberrypi-kernel_1%3a1.20230405-1_armhf.deb ...

The above is a trimmed log, and the script then tries to apply kernel headers that don't match my system. I then get a scary fullscreen warning that tells me to please reboot, but when I do and reinstall, the same happens.

I'll focus on these warnings from the log above (and the messages that follow):

dpkg-query: package 'linux-headers-' is not installed
dpkg-query: package '6.1.21+' is not installed

From what I understand, the issue is with the get_kernel_version() macro and specifically this line:

$ dd if=$ZIMAGE obs=64K ibs=4 skip=$(( IMG_OFFSET / 4)) 2>/dev/null | zcat | grep -a -m1 "Linux version" | strings
initcall_blacklist
setup_command_line
print_unknown_bootoptions
do_initcalls
initcall_debug
initcall
Linux version 6.1.21+ (dom@buildbot) (arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-3ubuntu1) 8.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #

When this gets piped into awk, a lot of empty lines stay in the output, confusing the dpkg commands later on.

aplay whatever.wav still works without this.

I'm not sure this is the best fix, or if it should be applied in other scripts.

HinTak commented 1 year ago

Not quite. You should consider the line which calculates the offset:

IMG_OFFSET=$(LC_ALL=C grep -abo $'\x1f\x8b\x08\x00' $ZIMAGE | head -n 1 | cut -d ':' -f 1)

Which is then used in the version extraction. I don't know where 1f 8b 08 00 comes from, but that may need changing in 6.x . Or say, needs head -n 2 | tail -n 1 to select the 2nd value instead of the first with head -n 1.

HinTak commented 1 year ago

Slightly better fix : https://github.com/HinTak/seeed-voicecard/commit/a57389693ceae6daabd2a78ce488795a8d0125dd - see log message for explanation.

HinTak commented 1 year ago

A slightly longer explanation: those text extraction hacks basically looks for the first line of the boot up message, which is baked into the kernel, reporting its own version and what compiler was used etc.

It is among other boot messages, and each message tend to have a new line at the end. Logically it is the first message printed, but structurally it used to be in the middle among others in 5.x . It seems to be the first structurally too in 6.x, so before it, is just other executable structures, like routine names, without a newline separating.

Such rearrangements happen sometimes because of actual code change (blocks of message definitions moved / re-arranged), sometimes change in compiler and / or optimization level. So it is probably surprising how it works well for a few years. This breakage s probably either an actual person optimising the code (rearranging messages in order of their actual usage) or compiler optimized.

GuillaumeRossolini commented 1 year ago

A naive question: why not use something like uname -r instead? Seems like it outputs the string the install script needs.

HinTak commented 1 year ago

I think I use it in mine. But it is a 3-way problem: the running kernel, the installed kernel, and the installed header. Right after a general "apt upgrade" , they don't necessarily agree. I think I would abort and recommend a reboot; but the dkms system is supposed to rebuild after next reboot, so historically the important version is the installed kernel (which is the one used after reboot), rather than the current running kernel before reboot.

HinTak commented 1 year ago

Also the pi people are not very consistent between kernel self-reported version (from uname -r) vs the packaging (mostly time date snapshotted)

GuillaumeRossolini commented 1 year ago

Thanks for all the interesting information!