Hexxeh / rpi-firmware

Firmware files for the Raspberry Pi
Other
775 stars 208 forks source link

Kernel 4.8.13 kernel.img format changed. #132

Closed MrEngman closed 7 years ago

MrEngman commented 7 years ago

Updated to kernel 4.8.13 on a couple of Pis and I've found it has stopped my wifi compiler and wifi install scripts working due to a change in the kernel.img format. With previous kernel versions available via rpi-update the kernel images included a copy of uname_string embedded at the end of the kernel image files. Kernel 4.8.13 no longer has the uname_string included at the end of the kernel.img files and this has killed my scripts as it includes the info on kernel version and build that is used to help generate the wifi driver filenames to associate the right version of the driver with the right kernel version for the install script. Is this a new standard kernel image format or a temporary hiccup?

I compile a variety of out of tree wifi drivers using a script that uses the Hexxeh/rpi-firmware commit ID to determine the kernel to build for and create a compatible file name that the install script uses to install the right driver for the kernel version it is compiled for. As uname_string is not included in the Hexxeh/rpi-firmware commits I use the uname_string included in the kernel images to get the info to help create a the filename. With the new 4.813 kernel this info is missing so it is now necessary to manually update the script to generate a compatible wifi driver filename. The wifi install script uses a similar arrangement to automatically install the right driver for the kernel version being used or installed using rpi-update and so that now has stopped woring as well.

FYI following is the section of the wifi compiler script that gets the kernel version and build number used to generate the driver filename using the filename format driver-kernel-build.tar.gz where driver can be 8188eu, 8192eu, 8812au, mt7610 or mt7612 and kernel is the image kernel version without the + sign and build is the build number without the # sign. eg 8192eu-4.4.37-v7-936.tar.gz for the 8192eu drive for kernel 4.4.37-v7+, build #936

get_kernel_info() {
# get linux commit-id
        if ! (wget -q https://github.com/Hexxeh/rpi-firmware/raw/$rpi_firmware_commit_id/git_hash -O .git_hash) ; then
                echo "Cannot download kernel data."
                exit 1
        fi

        kernel_commit_id=$(cat .git_hash)

# get kernel image
        if ! (wget -q https://github.com/Hexxeh/rpi-firmware/raw/$rpi_firmware_commit_id/kernel.img -O .kernel) ; then
                echo "Cannot download kernel data."
                rm .git_hash
                exit 1
        fi

# extract uname_string from kernel image
        strings -n 10 .kernel | grep "Linux version" > .uname_string
        kernel=$(cat .uname_string | awk '{print $3}' | tr -d '+')
        build=$(grep -Po '(?<=#)[^[]*' .uname_string | awk '{print $1}')

        if (wget -q https://github.com/Hexxeh/rpi-firmware/raw/$rpi_firmware_commit_id/kernel7.img -O .kernel) ; then
                strings -n 10 .kernel | grep "Linux version" > .uname_string
                kernel7=$(cat .uname_string | awk '{print $3}' | tr -d '+')
                build7=$(grep -Po '(?<=#)[^[]*' .uname_string | awk '{print $1}')
        fi

# need to uncomment the following 4 lines to compile for kernel 4.8.13
#       kernel=4.8.13
#       kernel7=4.8.13-v7
#       build=937
#       build7=937

        echo "kernel= $kernel+"
        echo "kernel7 = $kernel7+"
        echo "build= #$build"
        echo "build7= #$build7"
        echo "kernel commit-id = $kernel_commit_id"

        rm .git_hash .kernel .uname_string
}

Using my compile script compiling for kernel 4.4.37 generates the following

richard@Karaj:~$ comp/wifi-compiler.sh 8192eu df7fffc29d6f0e561f324699d0018756a0d0afbc
rpi_firmware_commit_id = df7fffc29d6f0e561f324699d0018756a0d0afbc
kernel= 4.4.37+
kernel7 = 4.4.37-v7+
build= #936
build7= #936
kernel commit-id = 830c04fea80e48ecf1de1fc64c703b495713af17

however, compiling for kernel 4.8.13 using the script unmodified gives

richard@Karaj:~$ comp/wifi-compiler.sh 8192eu 7a47836821b92efa569500b3382b1812082e42d3
rpi_firmware_commit_id = 7a47836821b92efa569500b3382b1812082e42d3
kernel= +
kernel7 = +
build= #
build7= #
kernel commit-id = 430587d6949e71d5eec9cf6ebd90106c11d2e08c
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mrproper

and the kernel version and build number values to create the driver filenames are blank.

Hopefully this is just a typical temporary hiccup and not a new standard kernel image format.

MrEngman

popcornmix commented 7 years ago

Ping @pelwell The full string extracted is

DTOKLinux version 4.4.37+ (dc4@dc4-XPS13-9333) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611) ) #936 Fri Dec 9 16:53:10 GMT 2016

which is actually from the trailer appended with the mkknlimg tool. The use of mkknlimg tool has been deprecated for a while (it works fine without it and it does cause a problem in some circumstances). Phil suggested removing it a few days back.

Unfortunately this change isn't 4.8 only - it is a change to the build script so will affect the next 4.4 kernel too.

I think we need to find a better way of determining the kernel version.

rpi-firmware repo contains a git_hash file. That is 430587d6949e71d5eec9cf6ebd90106c11d2e08c on next currently. Can you use that? E.g.

curl -qL https://github.com/raspberrypi/linux/raw/430587d6949e71d5eec9cf6ebd90106c11d2e08c/Makefile 2>/dev/null | head -3
VERSION = 4
PATCHLEVEL = 8
SUBLEVEL = 13
MrEngman commented 7 years ago

Hi,

I do use git_hash to get the kernel commit to select the necessary kernel source from my git clone but my main issue is still determining the kernel version and build to ensure the wifi driver and the kernel version it is compiled for are correctly associated.

Just using the kernel Makefile to determine the kernel version can have problems. In the past I've found certain kernels, although having the same version number, required the driver recompiling to work with different builds. A little unusual, but it has happened occasionally, hence why I compile a new driver for each kernel build whenever a new commit appears in hexxeh/rpi-firmware.

I do remember spending a lot of time trying to figure out how to access uname_string in raspberrypi/firmware/extra but it proved impossible for me when trying to associate a random hexxeh/rpi-firmware commit with a particular commit in raspberrypi/firmware.

The easiest solution for me would probably be to have uname_string from raspberrypi/firmware/extra included in hexxeh/rpi-firmware. I'm fairly certain I did suggest this somewhere in the forum or on github a couple of years ago but unfortunately nothing happened.

One final point. I currently run most of my Pis headless using wifi. My wifi install script would allow me to run rpi-update to update the kernel and then install a new driver version for the kernel update before rebooting to run with the updated kernel. The change to the kernel format has stopped that script working and I now have to update the wifi manually first checking the new kernel version and build online then downloading and installing manually. And there are quite a few others out there using my script as well so they probably won't be too pleased with the change either.

Just notice another issue. /proc/cpuinfo reports the same hardware, BCM2835, for a B+ and a 2B where previously it showed, I think, BCM2708 for the B+ and BCM2709 for the 2B. So some more changes to the scripts to determine if it's armv6 or armv7 to load the right driver version. Oh well.

Anyway, thanks for your time and I will see what I can do to sort out my problems with the scripts.

MrEngman

popcornmix commented 7 years ago

Yes, upstream kernel (which we are moving towards) uses 2835 for both platforms. grep -c processor /proc/cpuinfo Should return 1 for single core Pi 1 style boards and 4 for multi core Pi2/Pi3 boards.

Adding uname_string to hexxeh repo is a possibility if we can't find a solution for this issue.

pelwell commented 7 years ago

There are a few options here, not mutually exclusive:

  1. Modify the firmware to reduce the differences between the handling of kernels with and without the trailer.

  2. Modify mkknlimg with an option to only add the kernel version string. We would still not use it by default, but we could guarantee that it does not change the firmware behaviour with respect to the kernel.

  3. You can run mkknlimg yourself to add the trailer as part of your flow, or extract the but that reads the kernel version from the compressed image.

  4. As popcornmix says, we can look at other ways to determine the kernel version, but I can see that a method requiring internet access might not be so desirable.

I think option 1 is sensible anyway, at least in respect of the overlay loading.

MrEngman commented 7 years ago

Hi Phil,

Sorry but my knowledge of the internels of linux are very limited. Not sure what you are trying to suggest as all I need to do is determine the kernel version and build whenever a new commit is added to the hexxeh repo and I have no idea what mkknlimg is. As the kernel image included the kernel version and build info so I grabbed the data from there. As far as I can see the simplest way to solve the problem would be to add uname_string to the hexxeh repo, rather like Module(7).symvers and git_hash were added a couple of years ago, 7 Apr 2014 commit 683516a to be precise.

Currently I can determine when a new commit is added to the hexxeh repo so update my kernel source from the kernel repo and then compile my wifi drivers and push to dropbox to make them available for whoever wants to use them and if I want to can then run rpi-update and the wifi install script to update to the new kernel and install the new out of tree drivers and then reboot to keep my headless Pis running using only wifi. This even means I can run a Pi Zero headless using only wifi and update the kernel and wifi drivers using rpi-update and my install script with no problems, until now of course. The install script can also be used to automatically install a wifi driver to a currently running kernel which fortunately still works.

If it's any use you can get my current wifi compiler and install scripts here.

https://dl.dropboxusercontent.com/u/80256631/wifi-compiler.tar.gz https://dl.dropboxusercontent.com/u/80256631/install-wifi.tar.gz

MrEngman

pelwell commented 7 years ago

Sorry MrEngman, I'll try and give a bit more information (I found WiFi now).

mkknlimg is a Perl script I added to the scripts folder of the raspberrypi/linux repo. It searches the kernel image for various strings, trying various decompression methods until it finds one that works. It wouldn't be hard to modify it to just extract and print the kernel version string.

MrEngman commented 7 years ago

Thanks, sounds helpful. I'll take a look and see what I can make of it. Now off to learn about using perl ;)

MrEngman

MrEngman commented 7 years ago

Hi Phil,

Well, your suggestion to use mkknlimg seems to have done the trick. Basically I just modified my scripts to check if extracting the Kernel version from the kernel.img left a blank uname_string and if it did then run mkknlimg in my current script essentially as it is, other than deleting a few lines that printed the values detected, to create a new kernel.img image from the original image but now with the Kernel version string included. Then continued my script as it is but extracting the kernel version and build from the updated kernel.img file and all works OK.

Just one item I'm not to happy about and that is that when running the wifi-install script to update the wifi drivers if a user wants to use rpi-update to update the kernel, rather than installing for the currently running kernel, the user needs to have mkknlimg installed so the script can determine the new kernel version being installed and so is able to grab the right version of the driver to install. I've updated the wifi script to automatically install mkknlimg if the user does not have it installed and it appears to work but am not to happy about that.

On the whole. although everything appears to be working OK which is what I was looking to achieve, I find it rather heavy handed and I would still like to suggest that uname_string(7) in the raspberrypi firmware repo be copied to the hexxeh firmware repo just like Module(7).symvers and git_hash were as I think the reasoning to do it must be just the same as it was then. It would make the scripts much simpler and require far less internet access, upto about 300 bytes rather than ~8MB, and no need to require mkknlimg installing to install the wifi drivers.

Thanks very much for your help.

MrEngman

Ruffio commented 7 years ago

@pelwell What do you say to @MrEngman suggestion?

pelwell commented 7 years ago

The firmware repo is @popcornmix's domain, but he did say above that adding uname_string to the repo is a possibility.

Personally, I don't think that added a cut-down mkknlimg to the wifi install script is the least amount of work all round.

Ruffio commented 7 years ago

@pelwell I understand that @MrEngman has a working solution and thereby has achieved his goal, however I also understand the big difference between 300 bytes vs 8MB. As RPI are small devices I think that keeping unnecessary transfers to a minimum should be a goal too.

pelwell commented 7 years ago

Do you understand where the those numbers you are quoting come from? The full mkknlimg script is under 6KB, so a cut-down version would be smaller still.

Ruffio commented 7 years ago

@pelwell definitely not, I don't know where the numbers are coming from, but that is not the point. Al too many issues never sees a closure so that is why I'm trying to ask questions so we can get them closed if they are resolved, or if nothing is going to be changed. What I see to much is that nobody from the foundation takes ownership and pride in having a top notch product by closing issues that aren't really an issues. Some cases can be real issues that 'must' be fixed and are fixed, some are feature requests. No matter what the case is, it should be dealt with, and not just hanging around. In this case, if the feature request is never going to be meet, then state that and try to explain the reason why it is not going to be changed/implemented. There can be a lot of good reasons not to do what the users wants, just explain it. If however the case is going to be implemented, then state that with an eta/priority. Just leaving a case/issue unresponded is never a good style even thought it is often used. Take action, make a decision, write it in the 'issues', get them closed so we can move on. Having a lot of open/half closed issues/feature requests hanging for years gives an unprofessional impression of the devices, and I don't guess that is the intention.

pelwell commented 7 years ago

...

Let's give MrEngman time to respond. If he can say clearly why the proposed solution isn't fit for purpose then we will consider the options.

MrEngman commented 7 years ago

Hi guys,

Good to see this issue is still being looked at. I would say that adding uname-string to the Hexxex/rpi-firmware repo would be ideal. Would save a lot of work and downloading.

Running the script to download a wifi driver for the currently running kernel is no issue. However, one important aspect of the install-wifi script as far as I'm concerned is that it can install a new driver if one wanted to use rpi-update or rpi-update commit-id so enables one to use a Pi with only a wifi connection and run rpi-update and before rebooting update the wifi with the install-wifi script and then after rebooting will run the new kernel with the updated wifi driver. It will also allow a new driver to be installed if running apt-get upgrade/dist-upgrade and a new kernel version is loaded so when the Pi is rebooted the wifi will be running with the updated driver but in this case determining the kernel version is rather more complicated.

The main issue is determining the kernel version and build that would be installed. As uname_string is not available in hexxeh/rpi-firmware currently I download the kernel image and for kernels using the old format extract uname_string from it or for the new kernel versions use mkknlimg to create uname_string and then extract the kernel version and build from uname_string to determine the wifi driver to install.

@pelwell , This is where the 8MB download comes from. Running the script to check if a driver is available requires downloading the kernel.img to determine the kernel version/build, and then running the script again if a driver is available to download and install the new driver downloads the kernel.img again.

So you can check if a driver is available using command sudo install-wifi -c rpi-update or sudo install-wifi -c commit-id to revert to a specific kernel version. Then if a driver is available run command sudo rpi-update && sudo install-wifi -u rpi-update which will update the rpi firmware and wifi driver. Then, after rebooting, the Pi should be running with the updated kernel/firmware and the updated wifi driver. So no need for ethernet cables to install a new wifi driver either.

If uname_string is available in the repo it would save a lot of downloading. Also with the change to the kernel.img format mkknlimg is needed to determine the kernel version. If mkknlimg is needed the script will download a slightly modified version and install it, with a minor name change, so it can be used by the script as and when required. If uname_string was available there would be no need to require using mkknlimg.

FYI the current version of the script is here https://dl.dropboxusercontent.com/u/80256631/install-wifi if you want to see how it does its stuff. Look at the check_driver() routine to see why uname_string would make life much easier and simpler.

EDIT: I use a similar format in my wifi compiler script to enable me to compile the wifi drivers I make available without needing to download/install a new kernel first.

XECDesign commented 7 years ago

@Ruffio Leaving an issue open leaves it easily searchable for people who might stumble upon the same problem. For example, I have an issue open from 2012 (https://github.com/raspberrypi/linux/issues/27). For technical reasons, it's unlikely to ever be fixed, but leaving it open serves as a record of the fact that it exists and saves people from going through the trouble of re-discovering it. Closing it to 'look professional' is only sweeping it under the carpet.

In the ideal world, there would only be a handful of open issues at a time, but that could be a full time job for a several people. Even then, some of these issues touch on topics only a few people are even capable of addressing. Lecturing engineers who might already be stretched thin on how to do their job and saying they don't take pride in their work is not going to solve the problem. Github issues are not the place to do that anyway. If it's a discussion you want to have, do it privately or on the forum.

pelwell commented 7 years ago

@MrEngman Thanks, that makes sense. The "check before rpi-update" feature was the missing piece of the puzzle. The fact that the issue has morphed from "it's broken" to "can we make it better" doesn't help.

I think you provide a valuable service to the Pi community and we'd like to support you, it is just a matter of finding time to make that change.

Ruffio commented 7 years ago

@MrEngman sorry for cluttering your issue :-(

@XECDesign I don't know what search engine you use, but Google can find closed issues too ;-) If there has been no closure/explanation for doing a thing or not doing it, then the user that finds this issue is still left in the dark. By answering and coming with comments then all other users can read the status of a specific issue and find guidance. By leaving an issue open with no kind of indication of progress/status or if it is ever going to be implemented then one is leaving the users in the dark. That is why I'm pinging for answers, both users and developers. You can check the repositories yourself, but remember that some of the issues where I have pinged people, they are now closed :-) No one is lecturing, if that is what you think, then you have missed the whole point and can go to the forum

MrEngman commented 7 years ago

@pelwell Thank you. I don't know how many people use the script but quite a few I guess so being able to use uname_string could save a lot of internet access to the repo.

popcornmix commented 7 years ago

So @pelwell you are happy adding uname_string and uname_string7 to rpi-firmware? At root level or create an extra directory like firmware does?

popcornmix commented 7 years ago

Also do we want these files in every user's boot directory? Or should rpi-update (optionally) remove them?

pelwell commented 7 years ago

I think they exist in the same category as "git_hash", i.e. metadata about the firmware release, so they can be handled in the same way (and stored in the same place). Once the Pi has booted they are of no real use because they just duplicate the existing uname information, so I would vote to not install (or subsequently delete) them.

popcornmix commented 7 years ago

@MrEngman Latest kernel update has added uname_string and uname_string7 to this repo. Is that good for you?

MrEngman commented 7 years ago

Excellent, thanks very much.

Off to update my scripts.

Ruffio commented 7 years ago

@MrEngman so this can be closed?

MrEngman commented 7 years ago

Certainly can