I am trying to have Yocto build a third-party driver and include it in my image. Specifically the driver for an Edimax EW-7811Un-V2 USB WiFi adapter.
I have got the driver working on the target machine by manually compiling and calling depmod, so I'm confident that it is supported.
Initially I tried replicating the manual process using the following .bb file:
DESCRIPTION="Driver for Edimax EW-7811Un-V2"
LICENSE="CLOSED"
LIC_FILES_CHKSUM=""
DEPENDS=""
INHIBIT_PACKAGE_STRIP="1"
SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"
S = "${WORKDIR}/ew7811un-v2-1.0.1.3"
do_compile {
oe_runmake_clean
oe_runmake
}
do_install() {
# This fails as Makefile does not respect DESTDIR
# There is an INSTALL_PREFIX variable, but it is not used in the install command
#oe_runmake install DESTDIR=${D}
# Instead call the install command directly
install -d ${D}/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless
install -p -m 644 8188eu.ko ${D}/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless
}
do_package_qa[noexec] = "1"
FILES_${PN} = "/lib/modules/4.14.98-2.2.0+gecb7f95/kernel/drivers/net/wireless/8188eu.ko"
This does not error but trying to load the module with modprobe
and insmod
on the target suggests the module was built for the wrong kernel version.
Checking log.do_compile
shows that make is run against kernel version 4.15.0-142-generic (the kernel version of the host machine) rather than 4.14-sumo.
I have also tried following the hello-mod_0.1.bb
example:
DESCRIPTION="Driver for Edimax EW-7811Un-V2"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
DEPENDS = ""
inherit module
SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"
S = "${WORKDIR}/ew7811un-v2-1.0.1.3"
RPROVIDES_${PN} += "kernel-module-${PN}"
but this fails to compile at all. Output includes recipe for target 'sub-make' failed
and I get a long list of errors beginning with warnings that __LINUX_ARCH_ARM__
is not defined.
Again this seems to use the host machine kernel headers rather than the target, even though bitbake outputs DISTRO_VERSION = "4.14-sumo".
Which is the correct way to add a driver to my image? Why are the host machine kernel headers being used rather than the targets?
I am now convinced that the correct method for building an out-of-tree kernel module is to follow the structure of module.bbclass
The .bb file in the question did not work because the provided Makefile did not follow expected conventions.
In particular I had to set the kernel source directory KSRC (rather than KERNEL_SRC specified in module.bbclass
) in order to use the target kernel headers.
I also had to overwrite the do_install() method as the Makefile did not provide a modules_install
target, and the install
target failed to create directories.
I ended up with the following .bb file:
DESCRIPTION = "Driver for Edimax EW-7811Un-V2"
LICENSE = "CLOSED"
LIC_FILES_CHKSUM = ""
DEPENDS = ""
inherit module
EXTRA_OEMAKE += "KSRC=${STAGING_KERNEL_DIR}"
SRC_URI = "file://ew7811un-v2-1.0.1.3.zip"
S = "${WORKDIR}/ew7811un-v2-1.0.1.3"
do_install() {
unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS
install -d ${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/wireless
install -p -m 644 8188eu.ko ${D}${nonarch_base_libdir}/modules/${KERNEL_VERSION}/kernel/drivers/net/wireless
if [ ! -e "${B}/${MODULES_MODULE_SYMVERS_LOCATION}/Module.symvers" ] ; then
bbwarn "Module.symvers not found in ${B}/${MODULES_MODULE_SYMVERS_LOCATION}"
bbwarn "Please consider setting MODULES_MODULE_SYMVERS_LOCATION to a"
bbwarn "directory below B to get correct inter-module dependencies"
else
install -Dm0644 "${B}/${MODULES_MODULE_SYMVERS_LOCATION}"/Module.symvers ${D}${includedir}/${BPN}/Module.symvers
# Module.symvers contains absolute path to the build directory.
# While it doesn't actually seem to matter which path is specified,
# clear them out to avoid confusion
sed -e 's:${B}/::g' -i ${D}${includedir}/${BPN}/Module.symvers
fi
}
RPROVIDES_${PN} += "kernel-module-${PN}"