"no symbol version for module_layout" when trying to load usbhid.ko
Solution 1:
Specifically what the problem is that when you built your module, the kernel source tree was probably missing the Modules.symvers file. The kbuild system actually warns you about this when you build your module. If Modules.symvers is missing, you'll see:
Warning: Symbol version dump /usr/src/linux-2.6.34-12/Modules.symvers is missing; modules will have no dependencies and modversions.
If your kernel has CONFIG_MODVERSIONS
enabled, then during the modpost phase of building your driver it will run scripts/mod/modpost with the -m option. If you're brave and take a look at the scripts/mod/modpost.c source, you'll see that the -m option adds the _module_layout_ symbol from vmlinux, however if you don't have Modules.symvers from your kernel, you'll not get the CRC value for this symbol and you'll end up with this error message.
So there are two ways around this.
1) run a full build of your running kernel to generate Modules.symvers, then rebuild your module. [http://www.mjmwired.net/kernel/Documentation/kbuild/modules.txt][1]
51 === 2. How to Build External Modules
52
53 To build external modules, you must have a prebuilt kernel available
54 that contains the configuration and header files used in the build.
55 Also, the kernel must have been built with modules enabled. If you are
56 using a distribution kernel, there will be a package for the kernel you
57 are running provided by your distribution.
58
59 An alternative is to use the "make" target "modules_prepare." This will
60 make sure the kernel contains the information required. The target
61 exists solely as a simple way to prepare a kernel source tree for
62 building external modules.
63
64 NOTE: "modules_prepare" will not build Module.symvers even if
65 CONFIG_MODVERSIONS is set; therefore, a full kernel build needs to be
66 executed to make module versioning work.
2) The other option is to tell stupid modprobe to just ignore all that crap and just load your module anyways:
modprobe -f <module>
I tend to favor option 2 :)
Solution 2:
Have both the linux-headers
and linux-source
packages corresponding to your kernel installed. For example for kernel 3.2.0-27-generic-pae
you need:
-
linux-headers-3.2.0-27-generic-pae
and -
linux-source-3.2.0-27-generic-pae
.
In case the version for the packages above doesn't match your running kernel version then you need to replace $(uname -r)
with the version string from your installed kernel package from above.
For the above example the package version is 3.2.0-27-generic-pae
. When you run uname -r
and its output is something different then 3.2.0-27-generic-pae
then you need to replace each $(uname -r)
below to match the version string from the installed packages.
-
cd /usr/src/linux-source-$Version
and unpack the .tar.bz2 archive in place and cd into the extracted directory - I guess you already did this -
cp /boot/config-$(uname -r) .config
into the kernel source directory -
cp /usr/src/linux-headers-$(uname -r)/Module.symvers .
into the kernel source directory
After you've done that, in the kernel source directory, do this:
make prepare
make scripts
-
make M=drivers/usb/serial
- change the path afterM=
to suit your needs
Unfortunately, I don't know how to build a specific module while keeping Module.symvers
untouched. Doing make drivers/usb/serial/option.ko
, for example, kills the Module.symvers
file, and you end up with your original problem. Using the M=
parameter doesn't kill it, but you have to build all the modules in the specified path - and I haven't found a way around it yet.